001: /*
002: * @(#)ConnectionSet.java 1.0 03-JUL-04
003: *
004: * Copyright (c) 2001-2004 Gaudenz Alder
005: *
006: */
007: package org.jgraph.graph;
008:
009: import java.io.Serializable;
010: import java.util.HashSet;
011: import java.util.Iterator;
012: import java.util.Map;
013: import java.util.Set;
014:
015: /**
016: * An object that represents a set of connections. Connections are equal, if
017: * equals returns true. Connections that are added later replace earlier
018: * connections.
019: *
020: * @version 1.0 1/1/02
021: * @author Gaudenz Alder
022: */
023:
024: public class ConnectionSet implements Serializable {
025:
026: /** Contents of the connection set. */
027: protected Set connections = new HashSet();
028:
029: /** Set of changed edges for the connection set. */
030: protected Set edges = new HashSet();
031:
032: /**
033: * Returns a connection set that represents the connection or disconnection
034: * of <code>cells</code> in <code>model</code> based on
035: * <code>disconnect</code>.
036: */
037: public static ConnectionSet create(GraphModel m, Object[] cells,
038: boolean disconnect) {
039: ConnectionSet cs = new ConnectionSet();
040: for (int i = 0; i < cells.length; i++) {
041: Object cell = cells[i];
042: // Edge
043: if (m.isEdge(cell)) {
044: if (disconnect)
045: cs.disconnect(cell);
046: else
047: cs.connect(cell, m.getSource(cell), m
048: .getTarget(cell));
049: }
050: // Port
051: Iterator it = m.edges(cell);
052: while (it.hasNext()) {
053: // Edge At Port
054: Object edge = it.next();
055: if (m.getSource(edge) == cell)
056: connect(cs, edge, cell, true, disconnect);
057: else if (m.getTarget(edge) == cell)
058: connect(cs, edge, cell, false, disconnect);
059: }
060: }
061: return cs;
062: }
063:
064: /**
065: * Constructs an empty ConnectionSet.
066: */
067: public ConnectionSet() {
068: }
069:
070: /**
071: * Constructs a ConnectionSet with one Connection.
072: */
073: public ConnectionSet(Object edge, Object port, boolean source) {
074: connect(edge, port, source);
075: }
076:
077: /**
078: * Constructs a connection set containing the specified connections and
079: * updates the set of changed edges.
080: */
081: public ConnectionSet(Set connections) {
082: setConnections(connections);
083: Iterator it = connections.iterator();
084: while (it.hasNext()) {
085: Connection conn = (Connection) it.next();
086: edges.add(conn.getEdge());
087: }
088: }
089:
090: /**
091: * Constructs a ConnectionSet with two Connections (to the source and target
092: * port of the edge).
093: */
094: public ConnectionSet(Object edge, Object source, Object target) {
095: connect(edge, source, target);
096: }
097:
098: /**
099: * Connect or disconnect <code>edge</code> from <code>source</code> and
100: * <code>target</code> in <code>cs</code> based on
101: * <code>disconnect</code>.
102: */
103: protected static void connect(ConnectionSet cs, Object edge,
104: Object port, boolean source, boolean disconnect) {
105: if (disconnect)
106: cs.disconnect(edge, source);
107: else
108: cs.connect(edge, port, source);
109: }
110:
111: /**
112: * Adds the connections in <code>views</code> to the connection set.
113: */
114: public void addConnections(CellView[] views) {
115: for (int i = 0; i < views.length; i++) {
116: if (views[i] instanceof EdgeView) {
117: EdgeView edgeView = (EdgeView) views[i];
118: Object edge = edgeView.getCell();
119: CellView sourceView = edgeView.getSource();
120: CellView targetView = edgeView.getTarget();
121: Object source = null;
122: if (sourceView != null)
123: source = sourceView.getCell();
124: Object target = null;
125: if (targetView != null)
126: target = targetView.getCell();
127: connect(edge, source, target);
128: }
129: }
130: }
131:
132: /**
133: * Connect <code>edge</code> to <code>source</code> and
134: * <code>target</code> in the connection set. The previous connections
135: * between <code>edge</code> and its source and target are replaced in the
136: * set.
137: */
138: public void connect(Object edge, Object source, Object target) {
139: connect(edge, source, true);
140: connect(edge, target, false);
141: }
142:
143: /**
144: * Connect <code>edge</code> to <code>port</code> passed in. The
145: * <code>source</code> indicates if <code>port</code> is the source of
146: * <code>edge</code> object. The previous connections between
147: * <code>edge</code> and its source or target in the set is replaced.
148: */
149: public void connect(Object edge, Object port, boolean source) {
150: Connection c = new Connection(edge, port, source);
151: connections.remove(c);
152: connections.add(c);
153: edges.add(edge);
154: }
155:
156: /**
157: * Disconnect <code>edge</code> from <code>source</code> and
158: * <code>target</code> in the connection set. The previous connections
159: * between <code>edge</code> and its source and target are replaced in the
160: * set.
161: */
162: public void disconnect(Object edge) {
163: disconnect(edge, true);
164: disconnect(edge, false);
165: }
166:
167: /**
168: * Disconnect <code>edge</code> from <code>port</code>.
169: * <code>source</code> indicates if <code>port</code> is the source of
170: * <code>edge</code>. The previous connections between <code>edge</code>
171: * and its source or target in the set is replaced.
172: */
173: public void disconnect(Object edge, boolean source) {
174: connections.add(new Connection(edge, null, source));
175: edges.add(edge);
176: }
177:
178: /**
179: * Returns <code>true</code> if the connection set is empty.
180: */
181: public boolean isEmpty() {
182: return connections.isEmpty();
183: }
184:
185: /**
186: * Returns the number of (edge, port)-pairs.
187: */
188: public int size() {
189: return connections.size();
190: }
191:
192: /**
193: * Returns an <code>Iterator</code> for the connections in this set.
194: */
195: public Iterator connections() {
196: return connections.iterator();
197: }
198:
199: /**
200: * Returns a <code>Set</code> for the edges in this connection set.
201: */
202: public Set getChangedEdges() {
203: return edges;
204: }
205:
206: /**
207: * Returns the source or target of the specified edge in this connection set
208: * or null if the connection set contains no corresponding entry for the
209: * edge.
210: */
211: public Object getPort(Object edge, boolean source) {
212: if (edges.contains(edge)) {
213: Iterator it = connections.iterator();
214: while (it.hasNext()) {
215: Connection c = (Connection) it.next();
216: if (c.getEdge() == edge && c.isSource() == source)
217: return c.getPort();
218: }
219: }
220: return null;
221: }
222:
223: /**
224: * Creates a new connection set based on this connection set, where the
225: * edges, and ports are mapped using <code>map</code>. If a port is not
226: * found, the old port is used. If both, the edge and the port are not in
227: * <code>map</code>, the entry is ignored.
228: * <p>
229: * <strong>Note: </strong> Consequently, unselected edges are only
230: * reconnected at the first "paste" after a "cut", because in this case the
231: * ConnectionSet is not cloned.
232: */
233: public ConnectionSet clone(Map map) {
234: ConnectionSet cs = new ConnectionSet();
235: Iterator it = connections();
236: while (it.hasNext()) {
237: // Shortcut Vars
238: Connection c = (Connection) it.next();
239: Object edge = map.get(c.getEdge());
240: Object port = c.getPort();
241: if (port != null)
242: port = map.get(port);
243: // New Port
244: if (edge != null && port != null)
245: cs.connect(edge, port, c.isSource());
246: // Old Port
247: else if (edge != null)
248: cs.connect(edge, c.getPort(), c.isSource());
249: }
250: return cs;
251: }
252:
253: /**
254: * Object that represents the connection between an edge and a port.
255: */
256: public static class Connection implements Serializable {
257:
258: /** The edge that will be connected to the port. */
259: protected Object edge;
260:
261: /** The port that will be connected to the edge. */
262: protected Object port;
263:
264: /** Indicates if <code>port</code> is the source of <code>edge</code>. */
265: protected boolean isSource;
266:
267: public Connection() {
268: // Empty Constructor
269: }
270:
271: /**
272: * Constructs a new source or target connection between
273: * <code>edge</code> and <code>port</code> based on the value of
274: * <code>source</code>
275: */
276: public Connection(Object edge, Object port, boolean isSource) {
277: this .edge = edge;
278: this .port = port;
279: this .isSource = isSource;
280: }
281:
282: /**
283: * Returns the edge of the connection.
284: */
285: public Object getEdge() {
286: return edge;
287: }
288:
289: /**
290: * Returns the port of the connection.
291: */
292: public Object getPort() {
293: return port;
294: }
295:
296: /**
297: * Returns <code>true</code> if <code>port</code> is the source of
298: * <code>edge</code>.
299: */
300: public boolean isSource() {
301: return isSource;
302: }
303:
304: /**
305: * Two connections are equal if they represent the source or target of
306: * the same edge. That is, if
307: * <p>
308: * c1.edge == c2.edge && c1.isSource == c2.isSource.
309: */
310: public boolean equals(Object obj) {
311: if (obj instanceof Connection) {
312: Connection other = (Connection) obj;
313: return (other.getEdge().equals(edge) && other
314: .isSource() == isSource);
315: }
316: return false;
317: }
318:
319: /**
320: * Ensure equality of hashCode wrt equals().
321: */
322: public int hashCode() {
323: return edge.hashCode();
324: }
325:
326: /**
327: * @param object
328: */
329: public void setEdge(Object object) {
330: edge = object;
331: }
332:
333: /**
334: * @param b
335: */
336: public void setSource(boolean b) {
337: isSource = b;
338: }
339:
340: /**
341: * @param object
342: */
343: public void setPort(Object object) {
344: port = object;
345: }
346:
347: }
348:
349: /**
350: * @return the set of connections
351: */
352: public Set getConnections() {
353: return connections;
354: }
355:
356: /**
357: * @return the edges making us this connection set
358: */
359: public Set getEdges() {
360: return edges;
361: }
362:
363: /**
364: * @param set
365: */
366: public void setConnections(Set set) {
367: connections = set;
368: }
369:
370: /**
371: * @param set
372: */
373: public void setEdges(Set set) {
374: edges = set;
375: }
376:
377: }
|