Repository navigation
Expand file tree
/
Copy pathConnection.java
More file actions
229 lines (210 loc) · 7.37 KB
/
Copy pathConnection.java
File metadata and controls
229 lines (210 loc) · 7.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/*
* This file is part of NodeBox.
*
* Copyright (C) 2008 Frederik De Bleser (frederik@pandora.be)
*
* NodeBox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NodeBox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NodeBox. If not, see <http://www.gnu.org/licenses/>.
*/
package nodebox.node;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a connection between two nodes.
* <p/>
* Connections are made between ports on the nodes. The connection goes from the output port of the output node
* (there is only one output port) to an input port on the input node.
* <p/>
* This class can only store the connection between one output and one input. Some nodes, such as the merge node,
* have multiple outputs that connect to the same input. These are connected using a MultiConnection.
*/
public class Connection {
private List<Port> outputs;
private Port input;
/**
* Creates a connection between the output (upstream) node and input (downstream) node.
*
* @param output the output (upstream) parameter
* @param input the input (downstream) parameter
*/
public Connection(Port output, Port input) {
assert output != null;
assert input != null;
this.outputs = new ArrayList<Port>(1);
this.outputs.add(output);
this.input = input;
}
/**
* Gets the first output (upstream) port.
*
* @return the output port.
*/
public Port getOutput() {
assert outputs.size() > 0;
return outputs.get(0);
}
public boolean hasOutput(Port port) {
return outputs.contains(port);
}
/**
* Get a list with all output ports in this connection.
*
* @return the list of output ports. This list can safely be modified.
*/
public List<Port> getOutputs() {
return new ArrayList<Port>(outputs);
}
/**
* Check if this connection still has any output ports.
*
* @return true if this connection has output ports.
*/
public boolean hasOutputs() {
return outputs.size() > 0;
}
/**
* Add the given output port to this connection.
*
* @param port the output port to add.
* @return true if the port was added, false if this connection already contains the output.
*/
public boolean addOutput(Port port) {
if (port == null)
throw new IllegalArgumentException("The given port cannot be null.");
if (outputs.contains(port)) return false;
// Sanity check to see if the output and input ports are not the same,
// which would cause infinite recursion.
if (port.getNode() == input.getNode())
throw new IllegalArgumentException("The output port cannot be on the same node as the input port.");
outputs.add(port);
return true;
}
/**
* Remove the given output port from this connection.
*
* @param port the port to remove
* @return true if there are no ouputs remaining.
* @throws IllegalArgumentException if the given port is not in this connection
*/
public boolean removeOutput(Port port) throws IllegalArgumentException {
if (!outputs.contains(port))
throw new IllegalArgumentException("The given port does not participate in this connection.");
outputs.remove(port);
return outputs.isEmpty();
}
/**
* Remove the given node from this connection.
*
* @param node the node to remove
* @return true if there are no ouputs remaining.
* @throws IllegalArgumentException if the given port is not in this connection
*/
public boolean removeOutputNode(Node node) throws IllegalArgumentException {
return removeOutput(node.getOutputPort());
}
/**
* Return the node for the first output port in this connection.
*
* @return a Node or null if there are no output ports
*/
public Node getOutputNode() {
if (outputs.size() == 0) return null;
return outputs.get(0).getNode();
}
/**
* Gets a list of all nodes for the output ports in this connection.
*
* @return a list of nodes. This list can safely be modified.
*/
public List<Node> getOutputNodes() {
List<Node> nodes = new ArrayList<Node>(1);
for (Port p : outputs) {
nodes.add(p.getNode());
}
return nodes;
}
/**
* Changes the ordering of output ports by moving the given port a specified number of positions.
* <p/>
* To move the specified port up one position, set the deltaIndex to -1. To move a port down, set
* the deltaIndex to 1.
* <p/>
* If the delta index is larger or smaller than the number of positions this port can move, it will
* move the port to the beginning or end. This will not result in an error.
*
* @param port the port to move
* @param deltaIndex the number of places to move.
*/
public void reorderOutput(Port port, int deltaIndex) {
int index = outputs.indexOf(port);
int newIndex = index + deltaIndex;
newIndex = Math.max(0, Math.min(outputs.size() - 1, newIndex));
if (index == newIndex) return;
outputs.remove(port);
outputs.add(newIndex, port);
markDirtyDownstream();
}
/**
* Gets the input (downstream) port.
*
* @return the input port.
*/
public Port getInput() {
return input;
}
/**
* Return the node for the input port in this connection.
*
* @return the Node for the input port.
*/
public Node getInputNode() {
if (input == null) return null;
return input.getNode();
}
public void markDirtyDownstream() {
getInputNode().markDirty();
}
/**
* Updates the connection.
* <p/>
* Updates all output nodes and combines the results, which is stored in the input port.
* <p/>
* Depending on the cardinality of the port, you can retrieve the value using getValue() or getValues().
*
* @param ctx the metadata about the update operation.
* @see nodebox.node.Port#getValue()
* @see nodebox.node.Port#getValues()
*/
public void update(ProcessingContext ctx) {
// TODO: Check if we can break the system with infinite recursion.
// Clear out the value(s) of the port.
input.reset();
if (input.getCardinality() == Port.Cardinality.SINGLE) {
Node node = getOutputNode();
node.update(ctx);
// TODO: We should clone the value here.
input.setValue(node.getOutputValue());
} else {
for (Port output : outputs) {
Node node = output.getNode();
node.update(ctx);
// TODO: We should clone the value here.
input.addValue(node.getOutputValue());
}
}
}
@Override
public String toString() {
return getOutputs() + " <= " + getInput();
}
}