Source Code Cross Referenced for DefaultGraphModel.java in  » Graphic-Library » jgraph » org » jgraph » graph » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Graphic Library » jgraph » org.jgraph.graph 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#)DefaultGraphModel.java	1.0 03-JUL-04
0003:         * 
0004:         * Copyright (c) 2001-2004 Gaudenz Alder
0005:         *  
0006:         */
0007:        package org.jgraph.graph;
0008:
0009:        import java.io.IOException;
0010:        import java.io.ObjectInputStream;
0011:        import java.io.Serializable;
0012:        import java.util.ArrayList;
0013:        import java.util.Collection;
0014:        import java.util.HashSet;
0015:        import java.util.Hashtable;
0016:        import java.util.Iterator;
0017:        import java.util.LinkedHashSet;
0018:        import java.util.LinkedList;
0019:        import java.util.List;
0020:        import java.util.Map;
0021:        import java.util.Set;
0022:        import java.util.Stack;
0023:
0024:        import javax.swing.event.EventListenerList;
0025:        import javax.swing.tree.DefaultMutableTreeNode;
0026:        import javax.swing.tree.MutableTreeNode;
0027:        import javax.swing.tree.TreeNode;
0028:        import javax.swing.undo.AbstractUndoableEdit;
0029:        import javax.swing.undo.CannotRedoException;
0030:        import javax.swing.undo.CannotUndoException;
0031:        import javax.swing.undo.CompoundEdit;
0032:        import javax.swing.undo.UndoableEdit;
0033:        import javax.swing.undo.UndoableEditSupport;
0034:
0035:        import org.jgraph.event.GraphModelEvent;
0036:        import org.jgraph.event.GraphModelListener;
0037:
0038:        /**
0039:         * A simple implementation of a graph model.
0040:         * 
0041:         * @version 1.0 1/1/02
0042:         * @author Gaudenz Alder
0043:         */
0044:
0045:        public class DefaultGraphModel extends UndoableEditSupport implements 
0046:                Serializable, GraphModel {
0047:
0048:            /**
0049:             * The list of listeners that listen to the model.
0050:             */
0051:            protected transient EventListenerList listenerList = new EventListenerList();
0052:
0053:            /**
0054:             * Default instance of an empty iterator.
0055:             */
0056:            protected transient Iterator emptyIterator = new EmptyIterator();
0057:
0058:            /**
0059:             * Set that contains all root cells of this model.
0060:             */
0061:            protected List roots = null;
0062:
0063:            /**
0064:             * Indicates whether isLeaf is based on a node's allowsChildren value.
0065:             */
0066:            protected boolean asksAllowsChildren = false;
0067:
0068:            /**
0069:             * Whether or not to remove group cells from the model when all of their
0070:             * children are removed
0071:             */
0072:            protected boolean removeEmptyGroups = true;
0073:
0074:            /**
0075:             * The model's own attributes as a map. Defaults to an empty Hashtable.
0076:             */
0077:            protected AttributeMap attributes = null;
0078:
0079:            /**
0080:             * A collection of unexecuted updates on this model
0081:             */
0082:            //	protected Collection currentUpdate = new ArrayList();
0083:            /**
0084:             * Whether or not an update is in the process of being dispatched
0085:             */
0086:            //	private transient boolean isDispatching = false;
0087:            /**
0088:             * Constructs a model that is not an attribute store.
0089:             */
0090:            public DefaultGraphModel() {
0091:                this (null, null);
0092:            }
0093:
0094:            /**
0095:             * Constructs a model that is not an attribute store.
0096:             */
0097:            public DefaultGraphModel(List roots, AttributeMap attributes) {
0098:                if (roots != null)
0099:                    this .roots = roots;
0100:                else
0101:                    this .roots = new ArrayList();
0102:                if (attributes != null)
0103:                    this .attributes = attributes;
0104:                else
0105:                    this .attributes = new AttributeMap();
0106:            }
0107:
0108:            /**
0109:             * Constructs a model using the specified information to construct the
0110:             * cells, attributes and connection data.
0111:             */
0112:            public DefaultGraphModel(List roots, AttributeMap attributes,
0113:                    ConnectionSet cs) {
0114:                this (roots, attributes);
0115:                handleConnectionSet(cs);
0116:            }
0117:
0118:            public List getRoots() {
0119:                return roots;
0120:            }
0121:
0122:            //
0123:            // Graph Model
0124:            //
0125:
0126:            /**
0127:             * Returns the number of roots in the model. Returns 0 if the model is
0128:             * empty.
0129:             * 
0130:             * @return the number of roots in the model
0131:             */
0132:            public int getRootCount() {
0133:                return roots.size();
0134:            }
0135:
0136:            /**
0137:             * Returns the root at index <I>index </I> in the model. This should not
0138:             * return null if <i>index </i> is a valid index for the model (that is
0139:             * <i>index </i>>= 0 && <i>index </i>< getRootCount()).
0140:             * 
0141:             * @return the root of at index <I>index </I>
0142:             */
0143:            public Object getRootAt(int index) {
0144:                return roots.get(index);
0145:            }
0146:
0147:            /**
0148:             * Returns the index of <code>root</code> in the model. If root is
0149:             * <code>null</code>, returns -1.
0150:             * 
0151:             * @param root
0152:             *            a root in the model, obtained from this data source
0153:             * @return the index of the root in the model, or -1 if the parent is
0154:             *         <code>null</code>
0155:             */
0156:            public int getIndexOfRoot(Object root) {
0157:                return roots.indexOf(root);
0158:            }
0159:
0160:            /**
0161:             * Returns <code>true</code> if <code>node</code> or one of its
0162:             * ancestors is in the model.
0163:             * 
0164:             * @return <code>true</code> if <code>node</code> is in the model
0165:             */
0166:            public boolean contains(Object node) {
0167:                Object parentNode = null;
0168:                while ((parentNode = getParent(node)) != null)
0169:                    node = parentNode;
0170:                return roots.contains(node);
0171:            }
0172:
0173:            /**
0174:             * Returns a <code>Map</code> that represents the attributes for the
0175:             * specified cell. This attributes have precedence over each view's
0176:             * attributes, regardless of isAttributeStore.
0177:             * 
0178:             * @return attributes of <code>node</code> as a <code>Map</code>
0179:             */
0180:            public AttributeMap getAttributes(Object node) {
0181:                if (node instanceof  GraphCell)
0182:                    return ((GraphCell) node).getAttributes();
0183:                else if (node == null)
0184:                    return attributes;
0185:                return null;
0186:            }
0187:
0188:            /**
0189:             * @return Returns the user object of the given cell. This implementation
0190:             *         checks if the cell is a default mutable tree node and returns
0191:             *         it's user object.
0192:             */
0193:            public Object getValue(Object cell) {
0194:                if (cell instanceof  DefaultMutableTreeNode)
0195:                    return ((DefaultMutableTreeNode) cell).getUserObject();
0196:                return null;
0197:            }
0198:
0199:            /**
0200:             * Returns the graph model's attribute. Shortcut to <code>
0201:             * getAttributes(null)</code>.
0202:             * 
0203:             * @return attributes of <code>node</code> as a <code>Map</code>
0204:             */
0205:            public Map getAttributes() {
0206:                return getAttributes(null);
0207:            }
0208:
0209:            //
0210:            // Graph Structure
0211:            //
0212:
0213:            /**
0214:             * Returns the source of <code>edge</code>. <I>edge </I> must be an
0215:             * object previously obtained from this data source.
0216:             * 
0217:             * @return <code>Object</code> that represents the source of <i>edge </i>
0218:             */
0219:            public Object getSource(Object edge) {
0220:                if (edge instanceof  Edge)
0221:                    return ((Edge) edge).getSource();
0222:                return null;
0223:            }
0224:
0225:            /**
0226:             * Returns the target of <code>edge</code>. <I>edge </I> must be an
0227:             * object previously obtained from this data source.
0228:             * 
0229:             * @return <code>Object</code> that represents the target of <i>edge </i>
0230:             */
0231:            public Object getTarget(Object edge) {
0232:                if (edge instanceof  Edge)
0233:                    return ((Edge) edge).getTarget();
0234:                return null;
0235:            }
0236:
0237:            /**
0238:             * Returns <code>true</code> if <code>port</code> is a valid source for
0239:             * <code>edge</code>. <I>edge </I> and <I>port </I> must be objects
0240:             * previously obtained from this data source.
0241:             * 
0242:             * @return <code>true</code> if <code>port</code> is a valid source for
0243:             *         <code>edge</code>.
0244:             */
0245:            public boolean acceptsSource(Object edge, Object port) {
0246:                return true;
0247:            }
0248:
0249:            /**
0250:             * Returns <code>true</code> if <code>port</code> is a valid target for
0251:             * <code>edge</code>. <I>edge </I> and <I>port </I> must be objects
0252:             * previously obtained from this data source.
0253:             * 
0254:             * @return <code>true</code> if <code>port</code> is a valid target for
0255:             *         <code>edge</code>.
0256:             */
0257:            public boolean acceptsTarget(Object edge, Object port) {
0258:                return true;
0259:            }
0260:
0261:            /**
0262:             * Returns an iterator of the edges connected to <code>port</code>.
0263:             * <I>port </I> must be a object previously obtained from this data source.
0264:             * This method never returns null.
0265:             * 
0266:             * @param port
0267:             *            a port in the graph, obtained from this data source
0268:             * @return <code>Iterator</code> that represents the connected edges
0269:             */
0270:            public Iterator edges(Object port) {
0271:                if (port instanceof  Port)
0272:                    return ((Port) port).edges();
0273:                return emptyIterator;
0274:            }
0275:
0276:            /**
0277:             * Returns <code>true</code> if <code>edge</code> is a valid edge.
0278:             * 
0279:             * @return <code>true</code> if <code>edge</code> is a valid edge.
0280:             */
0281:            public boolean isEdge(Object edge) {
0282:                return edge instanceof  Edge;
0283:            }
0284:
0285:            /**
0286:             * Returns <code>true</code> if <code>port</code> is a valid port,
0287:             * possibly supporting edge connection.
0288:             * 
0289:             * @return <code>true</code> if <code>port</code> is a valid port.
0290:             */
0291:            public boolean isPort(Object port) {
0292:                return port instanceof  Port;
0293:            }
0294:
0295:            /**
0296:             * A shortcut method to create a connection set that represents the
0297:             * connections in this model. Useful for encoding to avoid writing redundant
0298:             * connection data stored in the cells.
0299:             */
0300:            public ConnectionSet getConnectionSet() {
0301:                return ConnectionSet.create(this , DefaultGraphModel
0302:                        .getAll(this ), false);
0303:            }
0304:
0305:            //
0306:            // Group Structure
0307:            //
0308:
0309:            /**
0310:             * Returns a map of (cell, clone)-pairs for all <code>cells</code>. In
0311:             * the new array, all references are replaced with references to the cloned
0312:             * cells (ie parent or anchor). This method does only include children which
0313:             * are in <code>cells</code>. Use JGraph.getDescendants to get a complete
0314:             * list of all children.
0315:             */
0316:            public Map cloneCells(Object[] cells) {
0317:                Map map = new Hashtable();
0318:                // Add Cells to Queue
0319:                for (int i = 0; i < cells.length; i++)
0320:                    map.put(cells[i], cloneCell(cells[i]));
0321:                // Replace Parent and Anchors
0322:                Iterator it = map.entrySet().iterator();
0323:                Object obj, cell, parent;
0324:                while (it.hasNext()) {
0325:                    Map.Entry entry = (Map.Entry) it.next();
0326:                    obj = entry.getValue();
0327:                    cell = entry.getKey();
0328:
0329:                    // Replaces the cloned cell's parent with the parent's clone
0330:                    parent = getParent(cell);
0331:                    if (parent != null)
0332:                        parent = map.get(parent);
0333:                    if (parent != null)
0334:                        ((DefaultMutableTreeNode) parent)
0335:                                .add((DefaultMutableTreeNode) obj);
0336:
0337:                    // Replaces the anchors for ports
0338:                    if (obj instanceof  Port) {
0339:                        Object anchor = ((Port) obj).getAnchor();
0340:                        if (anchor != null)
0341:                            ((Port) obj).setAnchor((Port) map.get(anchor));
0342:                    }
0343:                }
0344:                return map;
0345:            }
0346:
0347:            /**
0348:             * Sets the parent of the specified cell.
0349:             */
0350:            protected void setParent(Object child, Object parent) {
0351:                if (child instanceof  DefaultMutableTreeNode
0352:                        && parent instanceof  DefaultMutableTreeNode) {
0353:                    DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) parent;
0354:                    parentNode.add((DefaultMutableTreeNode) child);
0355:                }
0356:            }
0357:
0358:            /**
0359:             * Creates a shallow copy of the cell including a copy of the user object.
0360:             * Subclassers can override the cloneUserObject to provide a custom user
0361:             * object cloning mechanism.
0362:             */
0363:            protected Object cloneCell(Object cellObj) {
0364:                if (cellObj instanceof  DefaultGraphCell) {
0365:                    // Clones the cell
0366:                    DefaultGraphCell cell = (DefaultGraphCell) cellObj;
0367:                    DefaultGraphCell clone = (DefaultGraphCell) cell.clone();
0368:                    // Clones the user object
0369:                    clone.setUserObject(cloneUserObject(cell.getUserObject()));
0370:                    return clone;
0371:                }
0372:                return cellObj;
0373:            }
0374:
0375:            /**
0376:             * Clones the user object. Helper method that is invoked from cloneCells.
0377:             * You must use cloneCells (or cloneCell for single cells) to get a deep
0378:             * copy of a clone. Subclassers must override this and valueForCellChanged
0379:             * to implement custom user objects. This implementation returns
0380:             * <code>object</code>.
0381:             */
0382:            protected Object cloneUserObject(Object userObject) {
0383:                return userObject;
0384:            }
0385:
0386:            /**
0387:             * Returns the parent of <I>child </I> in the model. <I>child </I> must be a
0388:             * node previously obtained from this data source. This returns null if
0389:             * <i>child </i> is a root in the model.
0390:             * 
0391:             * @param child
0392:             *            a node in the graph, obtained from this data source
0393:             * @return the parent of <I>child </I>
0394:             */
0395:            public Object getParent(Object child) {
0396:                if (child != null && child instanceof  TreeNode)
0397:                    return ((TreeNode) child).getParent();
0398:                return null;
0399:            }
0400:
0401:            /**
0402:             * Returns the index of child in parent. If either the parent or child is
0403:             * <code>null</code>, returns -1.
0404:             * 
0405:             * @param parent
0406:             *            a note in the tree, obtained from this data source
0407:             * @param child
0408:             *            the node we are interested in
0409:             * @return the index of the child in the parent, or -1 if either the parent
0410:             *         or the child is <code>null</code>
0411:             */
0412:            public int getIndexOfChild(Object parent, Object child) {
0413:                if (parent == null || child == null)
0414:                    return -1;
0415:                return ((TreeNode) parent).getIndex((TreeNode) child);
0416:            }
0417:
0418:            /**
0419:             * Returns the child of <I>parent </I> at index <I>index </I> in the
0420:             * parent's child array. <I>parent </I> must be a node previously obtained
0421:             * from this data source. This should not return null if <i>index </i> is a
0422:             * valid index for <i>parent </i> (that is <i>index </i>>= 0 && <i>index
0423:             * </i>< getChildCount( <i>parent </i>)).
0424:             * 
0425:             * @param parent
0426:             *            a node in the tree, obtained from this data source
0427:             * @return the child of <I>parent </I> at index <I>index </I>
0428:             */
0429:            public Object getChild(Object parent, int index) {
0430:                if (parent instanceof  TreeNode)
0431:                    return ((TreeNode) parent).getChildAt(index);
0432:                return null;
0433:            }
0434:
0435:            /**
0436:             * Returns the number of children of <I>parent </I>. Returns 0 if the node
0437:             * is a leaf or if it has no children. <I>parent </I> must be a node
0438:             * previously obtained from this data source.
0439:             * 
0440:             * @param parent
0441:             *            a node in the tree, obtained from this data source
0442:             * @return the number of children of the node <I>parent </I>
0443:             */
0444:            public int getChildCount(Object parent) {
0445:                if (parent instanceof  TreeNode)
0446:                    return ((TreeNode) parent).getChildCount();
0447:                return 0;
0448:            }
0449:
0450:            /**
0451:             * Returns whether the specified node is a leaf node. The way the test is
0452:             * performed depends on the.
0453:             * 
0454:             * @param node
0455:             *            the node to check
0456:             * @return true if the node is a leaf node
0457:             */
0458:            public boolean isLeaf(Object node) {
0459:                if (asksAllowsChildren && node instanceof  TreeNode)
0460:                    return !((TreeNode) node).getAllowsChildren();
0461:                return ((TreeNode) node).isLeaf();
0462:            }
0463:
0464:            //
0465:            // Change Support
0466:            //
0467:
0468:            /**
0469:             * Inserts the <code>roots</code> and connections into the model. Notifies
0470:             * the model- and undo listeners of the change. The passed-in edits are
0471:             * executed if they implement the
0472:             * <code>GraphModelEvent.ExecutableGraphChange</code> interface in
0473:             * ascending array-order, after execution of the model change. Note: The
0474:             * passed-in propertyMap may contain <code>PortView</code> s which must be
0475:             * turned into <code>Point</code> s when stored in the model.
0476:             */
0477:            public void insert(Object[] roots, Map attributes,
0478:                    ConnectionSet cs, ParentMap pm, UndoableEdit[] edits) {
0479:                GraphModelEdit edit = createEdit(roots, null, attributes, cs,
0480:                        pm, edits);
0481:                if (edit != null) {
0482:                    edit.execute(); // fires graphChangeEvent
0483:                    if (edits != null) {
0484:                        for (int i = 0; i < edits.length; i++)
0485:                            if (edits[i] instanceof  GraphLayoutCache.GraphLayoutCacheEdit)
0486:                                ((GraphLayoutCache.GraphLayoutCacheEdit) edits[i])
0487:                                        .execute();
0488:                    }
0489:                    postEdit(edit); // fires undoableedithappened
0490:                }
0491:            }
0492:
0493:            /**
0494:             * Removes <code>cells</code> from the model. Notifies the model- and undo
0495:             * listeners of the change.
0496:             */
0497:            public void remove(Object[] roots) {
0498:                GraphModelEdit edit = createRemoveEdit(roots);
0499:                if (edit != null) {
0500:                    edit.execute();
0501:                    postEdit(edit);
0502:                }
0503:            }
0504:
0505:            /**
0506:             * Shortcut to the new edit method which allows inserts and removes to go
0507:             * along with an edit.
0508:             */
0509:            public void edit(Map attributes, ConnectionSet cs, ParentMap pm,
0510:                    UndoableEdit[] edits) {
0511:                edit(null, null, attributes, cs, pm, edits);
0512:            }
0513:
0514:            /**
0515:             * Applies <code>attributes</code> and the connection changes to the
0516:             * model. The initial <code>edits</code> that triggered the call are
0517:             * considered to be part of this transaction. The passed-in edits are
0518:             * executed if they implement the
0519:             * <code>GraphModelEvent.ExecutableGraphChange</code> interface in
0520:             * ascending array-order, after execution of the model change. Notifies the
0521:             * model- and undo listeners of the change. <strong>Note: </strong> If only
0522:             * <code>edits</code> is non-null, the edits are directly passed to the
0523:             * UndoableEditListeners. Note: The passed-in propertyMap may contains
0524:             * PortViews which must be turned into Points when stored in the model.
0525:             */
0526:            public void edit(Object[] inserted, Object[] removed,
0527:                    Map attributes, ConnectionSet cs, ParentMap pm,
0528:                    UndoableEdit[] edits) {
0529:                if ((inserted == null || inserted.length == 0)
0530:                        && (removed == null || removed.length == 0)
0531:                        && (attributes == null || attributes.isEmpty())
0532:                        && (cs == null || cs.isEmpty()) && pm == null
0533:                        && edits != null && edits.length == 1) {
0534:                    if (edits[0] instanceof  GraphLayoutCache.GraphLayoutCacheEdit)
0535:                        ((GraphLayoutCache.GraphLayoutCacheEdit) edits[0])
0536:                                .execute();
0537:                    postEdit(edits[0]); // UndoableEdit Relay
0538:                } else {
0539:                    GraphModelEdit edit = createEdit(inserted, removed,
0540:                            attributes, cs, pm, edits);
0541:                    if (edit != null) {
0542:                        edit.execute();
0543:                        if (edits != null) {
0544:                            for (int i = 0; i < edits.length; i++)
0545:                                if (edits[i] instanceof  GraphLayoutCache.GraphLayoutCacheEdit)
0546:                                    ((GraphLayoutCache.GraphLayoutCacheEdit) edits[i])
0547:                                            .execute();
0548:                        }
0549:                        postEdit(edit);
0550:                    }
0551:                }
0552:            }
0553:
0554:            /*
0555:             * (non-Javadoc)
0556:             * 
0557:             * @see com.jgraph.model.GraphModel#execute(com.jgraph.model.DefaultGraphModel.Change)
0558:             */
0559:            public synchronized void execute(ExecutableChange change) {
0560:                //		change.execute();
0561:                //		beginUpdate();
0562:                //		currentUpdate.add(change);
0563:                //		endUpdate();
0564:            }
0565:
0566:            /*
0567:             * (non-Javadoc)
0568:             * 
0569:             * @see com.jgraph.model.GraphModel#getUpdateLevel()
0570:             */
0571:            public int getUpdateLevel() {
0572:                return super .getUpdateLevel();
0573:                //return updateLevel;
0574:            }
0575:
0576:            /*
0577:             * (non-Javadoc)
0578:             * 
0579:             * @see javax.swing.undo.UndoableEditSupport#beginUpdate()
0580:             */
0581:            public void beginUpdate() {
0582:                super .beginUpdate();
0583:                //updateLevel++;
0584:            }
0585:
0586:            /*
0587:             * (non-Javadoc)
0588:             * 
0589:             * @see com.jgraph.model.GraphModel#endUpdate()
0590:             */
0591:            public void endUpdate() {
0592:                super .endUpdate();
0593:                //		boolean dispatch = false;
0594:                //		synchronized (this) {
0595:                //			updateLevel--;
0596:                //			if (!isDispatching && updateLevel == 0) {
0597:                //				dispatch = true;
0598:                //				isDispatching = true;
0599:                //			}
0600:                //		}
0601:                //		if (dispatch) {
0602:                //			try {
0603:                //				if (!currentUpdate.isEmpty()) {
0604:                //					Collection changes = new ArrayList(currentUpdate);
0605:                //					currentUpdate.clear();
0606:                //					undoSupport
0607:                //							.postEdit(createEdit(processGraphChanges(changes)));
0608:                //				}
0609:                //			} finally {
0610:                //				isDispatching = false;
0611:                //			}
0612:                //		}
0613:            }
0614:
0615:            /**
0616:             * Sends <code>cells</code> to back.
0617:             */
0618:            public void toBack(Object[] cells) {
0619:                GraphModelLayerEdit edit = createLayerEdit(cells,
0620:                        GraphModelLayerEdit.BACK);
0621:                if (edit != null) {
0622:                    edit.execute();
0623:                    postEdit(edit);
0624:                }
0625:            }
0626:
0627:            /**
0628:             * Brings <code>cells</code> to front.
0629:             */
0630:            public void toFront(Object[] cells) {
0631:                GraphModelLayerEdit edit = createLayerEdit(cells,
0632:                        GraphModelLayerEdit.FRONT);
0633:                if (edit != null) {
0634:                    edit.execute();
0635:                    postEdit(edit);
0636:                }
0637:            }
0638:
0639:            protected GraphModelLayerEdit createLayerEdit(Object[] cells,
0640:                    int layer) {
0641:                return new GraphModelLayerEdit(cells, layer);
0642:            }
0643:
0644:            //
0645:            // Edit Creation
0646:            //
0647:
0648:            /**
0649:             * Returns an edit that represents an insert.
0650:             */
0651:            // protected GraphModelEdit createInsertEdit(Object[] cells, Map
0652:            // attributeMap,
0653:            // ConnectionSet cs, ParentMap pm, UndoableEdit[] edits) {
0654:            // return createEdit(cells, null, attributeMap, cs, pm, edits);
0655:            // }
0656:            /**
0657:             * Returns an edit that represents a remove.
0658:             */
0659:            protected GraphModelEdit createRemoveEdit(Object[] cells) {
0660:                // Remove from GraphStructure
0661:                ConnectionSet cs = ConnectionSet.create(this , cells, true);
0662:                // Remove from Group Structure
0663:                ParentMap pm = ParentMap.create(this , cells, true, false);
0664:                // Construct Edit
0665:                GraphModelEdit edit = createEdit(null, cells, null, cs, pm,
0666:                        null);
0667:                if (edit != null)
0668:                    edit.end();
0669:                return edit;
0670:            }
0671:
0672:            protected GraphModelEdit createEdit(Object[] inserted,
0673:                    Object[] removed, Map attributes, ConnectionSet cs,
0674:                    ParentMap pm, UndoableEdit[] edits) {
0675:                GraphModelEdit edit = new GraphModelEdit(inserted, removed,
0676:                        attributes, cs, pm);
0677:                if (edit != null) {
0678:                    if (edits != null)
0679:                        for (int i = 0; i < edits.length; i++)
0680:                            edit.addEdit(edits[i]);
0681:                    edit.end();
0682:                }
0683:                return edit;
0684:            }
0685:
0686:            //
0687:            // Change Handling
0688:            //
0689:
0690:            /**
0691:             * Inserts <code>cells</code> into the model. Returns the cells that were
0692:             * inserted (including descendants).
0693:             */
0694:            protected Object[] handleInsert(Object[] cells) {
0695:                Object[] inserted = null;
0696:                if (cells != null) {
0697:                    for (int i = 0; i < cells.length; i++)
0698:                        // Add to Roots if no parent
0699:                        if (getParent(cells[i]) == null)
0700:                            roots.add(cells[i]);
0701:                    // Return *all* inserted cells
0702:                    inserted = getDescendants(this , cells).toArray();
0703:                }
0704:                return inserted;
0705:            }
0706:
0707:            /**
0708:             * Removes <code>cells</code> from the model. Returns the cells that were
0709:             * removed as roots.
0710:             */
0711:            protected Object[] handleRemove(Object[] cells) {
0712:                Set removedRoots = new HashSet();
0713:                if (cells != null && cells.length > 0) {
0714:                    Set rootsSet = new HashSet(roots);
0715:                    for (int i = 0; i < cells.length; i++) {
0716:                        if (getParent(cells[i]) == null
0717:                                && rootsSet.contains(cells[i])) {
0718:                            removedRoots.add(cells[i]);
0719:                        }
0720:                    }
0721:                    if (removedRoots.size() > 0) {
0722:                        // If any roots have been removed, reform the roots
0723:                        // lists appropriately, keeping the order the same
0724:                        int newRootsSize = roots.size() - removedRoots.size();
0725:                        if (newRootsSize < 8) {
0726:                            newRootsSize = 8;
0727:                        }
0728:                        List newRoots = new ArrayList(newRootsSize);
0729:                        Iterator iter = roots.iterator();
0730:                        while (iter.hasNext()) {
0731:                            Object cell = iter.next();
0732:                            if (!removedRoots.contains(cell)) {
0733:                                newRoots.add(cell);
0734:                            }
0735:                        }
0736:                        roots = newRoots;
0737:                    }
0738:                }
0739:                return removedRoots.toArray();
0740:            }
0741:
0742:            /**
0743:             * Applies <code>cells</code> to the model. Returns a parent map that may
0744:             * be used to undo this change.
0745:             */
0746:            protected ParentMap handleParentMap(ParentMap parentMap) {
0747:                if (parentMap != null) {
0748:                    ParentMap undo = new ParentMap();
0749:                    HashSet rootsSet = null;
0750:                    HashSet rootsToBeRemoved = null;
0751:                    Iterator it = parentMap.entries();
0752:                    while (it.hasNext()) {
0753:                        ParentMap.Entry entry = (ParentMap.Entry) it.next();
0754:                        Object child = entry.getChild();
0755:                        Object parent = entry.getParent();
0756:                        undo.addEntry(child, getParent(child));
0757:                        if (parent == null) {
0758:                            if (child instanceof  MutableTreeNode) {
0759:                                ((MutableTreeNode) child).removeFromParent();
0760:                            }
0761:                        } else {
0762:                            if (parent instanceof  DefaultMutableTreeNode
0763:                                    && child instanceof  MutableTreeNode) {
0764:                                ((DefaultMutableTreeNode) parent)
0765:                                        .add((MutableTreeNode) child);
0766:                            }
0767:                        }
0768:
0769:                        if (rootsSet == null) {
0770:                            rootsSet = new HashSet(roots);
0771:                        }
0772:                        boolean isRoot = rootsSet.contains(child);
0773:                        if (parent == null && !isRoot) {
0774:                            rootsSet.add(child);
0775:                            roots.add(child);
0776:                        } else if (parent != null && isRoot) {
0777:                            if (rootsToBeRemoved == null) {
0778:                                rootsToBeRemoved = new HashSet();
0779:                            }
0780:                            rootsSet.remove(child);
0781:                            rootsToBeRemoved.add(child);
0782:                        }
0783:                    }
0784:                    if (rootsToBeRemoved != null && rootsToBeRemoved.size() > 0) {
0785:                        // If any roots have been removed, reform the roots
0786:                        // lists appropriately, keeping the order the same
0787:                        int newRootsSize = roots.size()
0788:                                - rootsToBeRemoved.size();
0789:                        if (newRootsSize < 8) {
0790:                            newRootsSize = 8;
0791:                        }
0792:                        List newRoots = new ArrayList(newRootsSize);
0793:                        Iterator iter = roots.iterator();
0794:                        while (iter.hasNext()) {
0795:                            Object cell = iter.next();
0796:                            if (!rootsToBeRemoved.contains(cell)) {
0797:                                newRoots.add(cell);
0798:                            }
0799:                        }
0800:                        roots = newRoots;
0801:                    }
0802:                    return undo;
0803:                }
0804:                return null;
0805:            }
0806:
0807:            /**
0808:             * Applies <code>attributes</code> to the cells specified as keys. Returns
0809:             * the <code>attributes</code> to undo the change.
0810:             */
0811:            protected Map handleAttributes(Map attributes) {
0812:                if (attributes != null) {
0813:                    Hashtable undo = new Hashtable(attributes.size());
0814:                    Iterator it = attributes.entrySet().iterator();
0815:                    while (it.hasNext()) {
0816:                        Map.Entry entry = (Map.Entry) it.next();
0817:                        Object cell = entry.getKey();
0818:                        Map deltaNew = (Map) entry.getValue();
0819:                        // System.out.println("deltaNew="+deltaNew);
0820:                        // System.out.println("stateOld="+getAttributes(cell));
0821:                        // Handle New Values
0822:                        Map deltaOld = null;
0823:                        AttributeMap attr = getAttributes(cell);
0824:                        if (attr != null) {
0825:                            deltaOld = attr.applyMap(deltaNew);
0826:                            // System.out.println("stateNew="+getAttributes(cell));
0827:                            // System.out.println("deltaOld="+deltaOld);
0828:                            undo.put(cell, deltaOld);
0829:                        } else {
0830:                            // Make room for the value
0831:                            deltaOld = new Hashtable(2);
0832:                        }
0833:                        // Handle new values
0834:                        Object newValue = deltaNew.get(GraphConstants.VALUE);
0835:                        if (newValue != null) {
0836:                            Object oldValue = valueForCellChanged(cell,
0837:                                    newValue);
0838:                            if (oldValue != null)
0839:                                GraphConstants.setValue(deltaOld, oldValue);
0840:                            // TODO: Userobject of null is probably invalid
0841:                            else
0842:                                GraphConstants.setRemoveAttributes(deltaOld,
0843:                                        new Object[] { GraphConstants.VALUE });
0844:                        } else {
0845:                            // Special case to handle removal of value attribute
0846:                            Object[] remove = GraphConstants
0847:                                    .getRemoveAttributes(deltaNew);
0848:                            if (remove != null && remove.length > 0) {
0849:                                for (int i = 0; i < remove.length; i++) {
0850:                                    if (remove[i] == GraphConstants.VALUE) {
0851:                                        Object oldValue = valueForCellChanged(
0852:                                                cell, null);
0853:                                        if (oldValue != null) {
0854:                                            GraphConstants.setValue(deltaOld,
0855:                                                    oldValue);
0856:                                        }
0857:                                    }
0858:                                }
0859:                            }
0860:                        }
0861:                    }
0862:                    return undo;
0863:                }
0864:                return null;
0865:            }
0866:
0867:            /**
0868:             * Applies the new value to the specified cell. Unfortunately for cloning
0869:             * the user object you must still override the attribute map and provide a
0870:             * custom cloneUserObject method. This is because the cloning of a cell is
0871:             * local to the cell, which in turn has a reference to its attribute map.
0872:             * 
0873:             * @param cell
0874:             * @param newValue
0875:             * @return the old value for the cell, if any
0876:             */
0877:            public Object valueForCellChanged(Object cell, Object newValue) {
0878:                if (cell instanceof  DefaultMutableTreeNode) {
0879:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) cell;
0880:                    Object oldValue = node.getUserObject();
0881:                    node.setUserObject(newValue);
0882:                    return oldValue;
0883:                }
0884:                return null;
0885:            }
0886:
0887:            //
0888:            // Connection Set Handling
0889:            //
0890:
0891:            /**
0892:             * Applies <code>connectionSet</code> to the model. Returns a connection
0893:             * set that may be used to undo this change.
0894:             */
0895:            protected ConnectionSet handleConnectionSet(ConnectionSet cs) {
0896:                if (cs != null) {
0897:                    ConnectionSet csundo = new ConnectionSet();
0898:                    Iterator it = cs.connections();
0899:                    while (it.hasNext()) {
0900:                        ConnectionSet.Connection c = (ConnectionSet.Connection) it
0901:                                .next();
0902:                        Object edge = c.getEdge();
0903:                        if (c.isSource())
0904:                            csundo.connect(edge, getSource(edge), true);
0905:                        else
0906:                            csundo.connect(edge, getTarget(edge), false);
0907:                        handleConnection(c, false);
0908:                    }
0909:
0910:                    // When removing edges it is possible that an edge is
0911:                    // removed in a later step which has been added in a
0912:                    // previous connection establishment (set semantic).
0913:                    // Therefore, we first need to remove all old connections
0914:                    // and then add all new connections in two steps.
0915:                    it = cs.connections();
0916:                    while (it.hasNext())
0917:                        handleConnection((ConnectionSet.Connection) it.next(),
0918:                                true);
0919:                    return csundo;
0920:                }
0921:                return null;
0922:            }
0923:
0924:            /**
0925:             * Inserts the specified connection into the model.
0926:             */
0927:            protected void handleConnection(ConnectionSet.Connection c,
0928:                    boolean establish) {
0929:                Object edge = c.getEdge();
0930:                Object port = (establish) ? c.getPort()
0931:                        : (c.isSource()) ? getSource(edge) : getTarget(edge);
0932:                connect(edge, port, c.isSource(), establish);
0933:            }
0934:
0935:            /**
0936:             * Connects or disconnects the edge and port in this model based on
0937:             * <code>remove</code>. Subclassers should override this to update
0938:             * connectivity datastructures.
0939:             */
0940:            protected void connect(Object edge, Object port, boolean isSource,
0941:                    boolean insert) {
0942:                if (port instanceof  Port)
0943:                    if (insert)
0944:                        ((Port) port).addEdge(edge);
0945:
0946:                    // Only removes if opposite is not
0947:                    // connected to same port
0948:                    else if ((isSource) ? getTarget(edge) != port
0949:                            : getSource(edge) != port)
0950:                        ((Port) port).removeEdge(edge);
0951:                if (!insert)
0952:                    port = null;
0953:                if (edge instanceof  Edge) {
0954:                    if (isSource)
0955:                        ((Edge) edge).setSource(port);
0956:                    else
0957:                        ((Edge) edge).setTarget(port);
0958:                }
0959:            }
0960:
0961:            //
0962:            // GraphModelListeners
0963:            //
0964:
0965:            /**
0966:             * Adds a listener for the GraphModelEvent posted after the graph changes.
0967:             * 
0968:             * @see #removeGraphModelListener
0969:             * @param l
0970:             *            the listener to add
0971:             */
0972:            public void addGraphModelListener(GraphModelListener l) {
0973:                listenerList.add(GraphModelListener.class, l);
0974:            }
0975:
0976:            /**
0977:             * Removes a listener previously added with <B>addGraphModelListener() </B>.
0978:             * 
0979:             * @see #addGraphModelListener
0980:             * @param l
0981:             *            the listener to remove
0982:             */
0983:            public void removeGraphModelListener(GraphModelListener l) {
0984:                listenerList.remove(GraphModelListener.class, l);
0985:            }
0986:
0987:            /**
0988:             * Invoke this method after you've changed how the cells are to be
0989:             * represented in the graph.
0990:             */
0991:            public void cellsChanged(final Object[] cells) {
0992:                if (cells != null) {
0993:                    fireGraphChanged(this ,
0994:                            new GraphModelEvent.GraphModelChange() {
0995:
0996:                                public Object[] getInserted() {
0997:                                    return null;
0998:                                }
0999:
1000:                                public Object[] getRemoved() {
1001:                                    return null;
1002:                                }
1003:
1004:                                public Map getPreviousAttributes() {
1005:                                    return null;
1006:                                }
1007:
1008:                                public ConnectionSet getConnectionSet() {
1009:                                    return null;
1010:                                }
1011:
1012:                                public ConnectionSet getPreviousConnectionSet() {
1013:                                    return null;
1014:                                }
1015:
1016:                                public ParentMap getParentMap() {
1017:                                    return null;
1018:                                }
1019:
1020:                                public ParentMap getPreviousParentMap() {
1021:                                    return null;
1022:                                }
1023:
1024:                                public void putViews(GraphLayoutCache view,
1025:                                        CellView[] cellViews) {
1026:                                }
1027:
1028:                                public CellView[] getViews(GraphLayoutCache view) {
1029:                                    return null;
1030:                                }
1031:
1032:                                public Object getSource() {
1033:                                    return this ;
1034:                                }
1035:
1036:                                public Object[] getChanged() {
1037:                                    return cells;
1038:                                }
1039:
1040:                                public Map getAttributes() {
1041:                                    return null;
1042:                                }
1043:
1044:                                public Object[] getContext() {
1045:                                    return null;
1046:                                }
1047:
1048:                            });
1049:                }
1050:            }
1051:
1052:            /*
1053:             * Notify all listeners that have registered interest for notification on
1054:             * this event type. The event instance is lazily created using the
1055:             * parameters passed into the fire method.
1056:             * 
1057:             * @see EventListenerList
1058:             */
1059:            protected void fireGraphChanged(Object source,
1060:                    GraphModelEvent.GraphModelChange edit) {
1061:                // Guaranteed to return a non-null array
1062:                Object[] listeners = listenerList.getListenerList();
1063:                GraphModelEvent e = null;
1064:                // Process the listeners last to first, notifying
1065:                // those that are interested in this event
1066:                for (int i = listeners.length - 2; i >= 0; i -= 2) {
1067:                    if (listeners[i] == GraphModelListener.class) {
1068:                        // Lazily create the event:
1069:                        if (e == null)
1070:                            e = new GraphModelEvent(source, edit);
1071:                        ((GraphModelListener) listeners[i + 1]).graphChanged(e);
1072:                    }
1073:                }
1074:            }
1075:
1076:            /**
1077:             * Return an array of all GraphModelListeners that were added to this model.
1078:             */
1079:            public GraphModelListener[] getGraphModelListeners() {
1080:                return (GraphModelListener[]) listenerList
1081:                        .getListeners(GraphModelListener.class);
1082:            }
1083:
1084:            //
1085:            // GraphModelEdit
1086:            //
1087:
1088:            /**
1089:             * An implementation of GraphModelChange that can be added to the model
1090:             * event.
1091:             */
1092:            public class GraphModelEdit extends CompoundEdit implements 
1093:                    GraphModelEvent.GraphModelChange {
1094:
1095:                /* Cells that were inserted/removed/changed during the last execution. */
1096:                protected Object[] insert, changed, remove, context;
1097:
1098:                /* Cells that were inserted/removed/changed during the last execution. */
1099:                protected Object[] inserted, removed;
1100:
1101:                /*
1102:                 * Property map for the next execution. Attribute Map is passed to the
1103:                 * views on inserts.
1104:                 */
1105:                protected Map attributes, previousAttributes;
1106:
1107:                /* Parent map for the next execution. */
1108:                protected ParentMap parentMap, previousParentMap;
1109:
1110:                /* ConnectionSet for the next execution. */
1111:                protected ConnectionSet connectionSet, previousConnectionSet;
1112:
1113:                /* Piggybacked undo from the views. */
1114:                protected Map cellViews = new Hashtable();
1115:
1116:                /**
1117:                 * Constructs an edit record.
1118:                 * 
1119:                 * @param inserted
1120:                 *            a set of roots that were inserted
1121:                 * @param removed
1122:                 *            a set of elements that were removed
1123:                 * @param attributes
1124:                 *            the attribute changes made by the edit
1125:                 * @param connectionSet
1126:                 *            the set of changed connections
1127:                 * @param parentMap
1128:                 *            the map of changed parents
1129:                 */
1130:                public GraphModelEdit(Object[] inserted, Object[] removed,
1131:                        Map attributes, ConnectionSet connectionSet,
1132:                        ParentMap parentMap) {
1133:                    super ();
1134:                    this .insert = inserted;
1135:                    this .remove = removed;
1136:                    this .connectionSet = connectionSet;
1137:                    this .attributes = attributes;
1138:                    this .parentMap = parentMap;
1139:                    previousAttributes = null;
1140:                    previousConnectionSet = connectionSet;
1141:                    previousParentMap = parentMap;
1142:                    // Remove Empty Parents
1143:                    if (parentMap != null) {
1144:                        // Compute Empty Group
1145:                        Map childCount = new Hashtable();
1146:                        Iterator it = parentMap.entries();
1147:                        while (it.hasNext()) {
1148:                            ParentMap.Entry entry = (ParentMap.Entry) it.next();
1149:                            Object child = entry.getChild();
1150:                            if (!isPort(child)) {
1151:                                Object oldParent = getParent(child);
1152:                                Object newParent = entry.getParent();
1153:                                if (oldParent != newParent) {
1154:                                    changeChildCount(childCount, oldParent, -1);
1155:                                    changeChildCount(childCount, newParent, 1);
1156:                                }
1157:                            }
1158:                        }
1159:                        handleEmptyGroups(filterParents(childCount, 0));
1160:                    }
1161:                }
1162:
1163:                public Object[] filterParents(Map childCount, int children) {
1164:                    ArrayList list = new ArrayList();
1165:                    Iterator it = childCount.entrySet().iterator();
1166:                    while (it.hasNext()) {
1167:                        Map.Entry entry = (Map.Entry) it.next();
1168:                        if (entry.getValue() instanceof  Integer) {
1169:                            if (((Integer) entry.getValue()).intValue() == children)
1170:                                list.add(entry.getKey());
1171:                        }
1172:                    }
1173:                    return list.toArray();
1174:                }
1175:
1176:                protected void changeChildCount(Map childCount, Object parent,
1177:                        int change) {
1178:                    if (parent != null) {
1179:                        Integer count = (Integer) childCount.get(parent);
1180:                        if (count == null) {
1181:                            count = new Integer(getChildCount(parent));
1182:                        }
1183:                        int newValue = count.intValue() + change;
1184:                        childCount.put(parent, new Integer(newValue));
1185:                    }
1186:                }
1187:
1188:                /**
1189:                 * Adds the groups that become empty to the cells that will be removed.
1190:                 * (Auto remove empty cells.) Removed cells will be re-inserted on undo,
1191:                 * and the parent- child relations will be restored.
1192:                 */
1193:                protected void handleEmptyGroups(Object[] groups) {
1194:                    if (removeEmptyGroups) {
1195:                        if (groups != null && groups.length > 0) {
1196:                            if (remove == null)
1197:                                remove = new Object[] {};
1198:                            Object[] tmp = new Object[remove.length
1199:                                    + groups.length];
1200:                            System.arraycopy(remove, 0, tmp, 0, remove.length);
1201:                            System.arraycopy(groups, 0, tmp, remove.length,
1202:                                    groups.length);
1203:                            remove = tmp;
1204:                        }
1205:                    }
1206:                }
1207:
1208:                public boolean isSignificant() {
1209:                    return true;
1210:                }
1211:
1212:                /**
1213:                 * Returns the source of this change. This can either be a view or a
1214:                 * model, if this change is a GraphModelChange.
1215:                 */
1216:                public Object getSource() {
1217:                    return DefaultGraphModel.this ;
1218:                }
1219:
1220:                /**
1221:                 * Returns the cells that have changed. This includes the cells that
1222:                 * have been changed through a call to getAttributes and the edges that
1223:                 * have been changed with the ConnectionSet.
1224:                 */
1225:                public Object[] getChanged() {
1226:                    return changed;
1227:                }
1228:
1229:                /**
1230:                 * Returns the objects that have not changed explicitly, but implicitly
1231:                 * because one of their dependent cells has changed.
1232:                 */
1233:                public Object[] getContext() {
1234:                    return context;
1235:                }
1236:
1237:                /**
1238:                 * Returns the cells that were inserted.
1239:                 */
1240:                public Object[] getInserted() {
1241:                    return inserted;
1242:                }
1243:
1244:                /**
1245:                 * Returns the cells that were inserted.
1246:                 */
1247:                public Object[] getRemoved() {
1248:                    return removed;
1249:                }
1250:
1251:                /**
1252:                 * Returns a map that contains (object, map) pairs of the attributes
1253:                 * that have been stored in the model.
1254:                 */
1255:                public Map getPreviousAttributes() {
1256:                    return previousAttributes;
1257:                }
1258:
1259:                /**
1260:                 * Returns a map of (object, view attributes). The objects are model
1261:                 * objects which need to be mapped to views.
1262:                 */
1263:                public Map getAttributes() {
1264:                    return attributes;
1265:                }
1266:
1267:                /**
1268:                 * Returns the connectionSet.
1269:                 * 
1270:                 * @return ConnectionSet
1271:                 */
1272:                public ConnectionSet getConnectionSet() {
1273:                    return connectionSet;
1274:                }
1275:
1276:                public ConnectionSet getPreviousConnectionSet() {
1277:                    return previousConnectionSet;
1278:                }
1279:
1280:                /**
1281:                 * Returns the parentMap.
1282:                 * 
1283:                 * @return ParentMap
1284:                 */
1285:                public ParentMap getParentMap() {
1286:                    return parentMap;
1287:                }
1288:
1289:                public ParentMap getPreviousParentMap() {
1290:                    return previousParentMap;
1291:                }
1292:
1293:                /**
1294:                 * Redoes a change.
1295:                 * 
1296:                 * @exception CannotRedoException
1297:                 *                if the change cannot be redone
1298:                 */
1299:                public void redo() throws CannotRedoException {
1300:                    super .redo();
1301:                    execute();
1302:                }
1303:
1304:                /**
1305:                 * Undoes a change.
1306:                 * 
1307:                 * @exception CannotUndoException
1308:                 *                if the change cannot be undone
1309:                 */
1310:                public void undo() throws CannotUndoException {
1311:                    super .undo();
1312:                    execute();
1313:                }
1314:
1315:                /**
1316:                 * Execute this edit such that the next invocation to this method will
1317:                 * invert the last execution.
1318:                 */
1319:                public void execute() {
1320:                    // Compute Changed Cells
1321:                    Set tmp = new HashSet();
1322:                    if (attributes != null)
1323:                        tmp.addAll(attributes.keySet());
1324:                    if (parentMap != null)
1325:                        tmp.addAll(parentMap.getChangedNodes());
1326:                    // Note: One must also include the previous parents!
1327:                    if (connectionSet != null)
1328:                        tmp.addAll(connectionSet.getChangedEdges());
1329:                    if (remove != null) {
1330:                        for (int i = 0; i < remove.length; i++)
1331:                            tmp.remove(remove[i]);
1332:                    }
1333:                    changed = tmp.toArray();
1334:                    // Context cells
1335:                    Set ctx = getEdges(DefaultGraphModel.this , changed);
1336:                    context = ctx.toArray();
1337:                    // Do Execute
1338:                    inserted = insert;
1339:                    removed = remove;
1340:                    remove = handleInsert(inserted);
1341:                    previousParentMap = parentMap;
1342:                    parentMap = handleParentMap(parentMap);
1343:                    // Adds previous parents
1344:                    if (parentMap != null)
1345:                        tmp.addAll(parentMap.getChangedNodes());
1346:                    previousConnectionSet = connectionSet;
1347:                    connectionSet = handleConnectionSet(connectionSet);
1348:                    insert = handleRemove(removed);
1349:                    previousAttributes = attributes;
1350:                    attributes = handleAttributes(attributes);
1351:                    changed = tmp.toArray();
1352:                    // Fire Event
1353:                    fireGraphChanged(DefaultGraphModel.this , this );
1354:                }
1355:
1356:                public void putViews(GraphLayoutCache view, CellView[] views) {
1357:                    if (view != null && views != null)
1358:                        cellViews.put(view, views);
1359:                }
1360:
1361:                public CellView[] getViews(GraphLayoutCache view) {
1362:                    return (CellView[]) cellViews.get(view);
1363:                }
1364:
1365:                public String toString() {
1366:                    String s = new String();
1367:                    if (inserted != null) {
1368:                        s += "Inserted:\n";
1369:                        for (int i = 0; i < inserted.length; i++)
1370:                            s += "  " + inserted[i] + "\n";
1371:                    } else
1372:                        s += "None inserted\n";
1373:                    if (removed != null) {
1374:                        s += "Removed:\n";
1375:                        for (int i = 0; i < removed.length; i++)
1376:                            s += "  " + removed[i] + "\n";
1377:                    } else
1378:                        s += "None removed\n";
1379:                    if (changed != null && changed.length > 0) {
1380:                        s += "Changed:\n";
1381:                        for (int i = 0; i < changed.length; i++)
1382:                            s += "  " + changed[i] + "\n";
1383:                    } else
1384:                        s += "None changed\n";
1385:                    if (parentMap != null)
1386:                        s += parentMap.toString();
1387:                    else
1388:                        s += "No parent map\n";
1389:                    return s;
1390:                }
1391:
1392:            }
1393:
1394:            /**
1395:             * An implementation of GraphViewChange.
1396:             */
1397:            public class GraphModelLayerEdit extends AbstractUndoableEdit
1398:                    implements  GraphModelEvent.GraphModelChange {
1399:
1400:                public static final int FRONT = -1, BACK = -2;
1401:
1402:                protected Object changeSource;
1403:
1404:                protected transient Object[] cells;
1405:
1406:                protected transient int[] next, prev;
1407:
1408:                protected int layer;
1409:
1410:                // The cell that change are the parents, because they need to
1411:                // reload their childs for reordering!
1412:                protected Object[] changed;
1413:
1414:                /**
1415:                 * Constructs a GraphModelEdit. This modifies the order of the cells in
1416:                 * the model.
1417:                 */
1418:                public GraphModelLayerEdit(Object[] cells, int layer) {
1419:                    this .cells = cells;
1420:                    this .layer = layer;
1421:                    next = new int[cells.length];
1422:                    prev = new int[cells.length];
1423:                    updateNext();
1424:                    // Compute array of changed cells (roots or parents of cells)
1425:                    Set par = new HashSet();
1426:                    for (int i = 0; i < cells.length; i++) {
1427:                        Object cell = DefaultGraphModel.this 
1428:                                .getParent(cells[i]);
1429:                        if (cell == null)
1430:                            cell = cells[i];
1431:                        par.add(cell);
1432:                    }
1433:                    changed = par.toArray();
1434:                }
1435:
1436:                protected void updateNext() {
1437:                    for (int i = 0; i < next.length; i++)
1438:                        next[i] = layer;
1439:                }
1440:
1441:                /**
1442:                 * Returns the source of this change. This can either be a view or a
1443:                 * model, if this change is a GraphModelChange.
1444:                 */
1445:                public Object getSource() {
1446:                    return DefaultGraphModel.this ;
1447:                }
1448:
1449:                /**
1450:                 * Returns the cells that have changed.
1451:                 */
1452:                public Object[] getChanged() {
1453:                    return changed;
1454:                }
1455:
1456:                /**
1457:                 * Returns the cells that have changed.
1458:                 */
1459:                public Object[] getInserted() {
1460:                    return null;
1461:                }
1462:
1463:                /**
1464:                 * Returns the cells that have changed.
1465:                 */
1466:                public Object[] getRemoved() {
1467:                    return null;
1468:                }
1469:
1470:                /**
1471:                 * Returns null.
1472:                 */
1473:                public Object[] getContext() {
1474:                    return null;
1475:                }
1476:
1477:                /**
1478:                 * Returns null.
1479:                 */
1480:                public Map getAttributes() {
1481:                    return null;
1482:                }
1483:
1484:                /**
1485:                 * Returns null.
1486:                 */
1487:                public Map getPreviousAttributes() {
1488:                    return null;
1489:                }
1490:
1491:                public ConnectionSet getConnectionSet() {
1492:                    return null;
1493:                }
1494:
1495:                public ConnectionSet getPreviousConnectionSet() {
1496:                    return null;
1497:                }
1498:
1499:                /**
1500:                 * Returns null.
1501:                 */
1502:                public ParentMap getParentMap() {
1503:                    return null;
1504:                }
1505:
1506:                public ParentMap getPreviousParentMap() {
1507:                    return null;
1508:                }
1509:
1510:                /**
1511:                 * Allows a <code>GraphLayoutCache</code> to add and execute and
1512:                 * UndoableEdit in this change. This does also work if the parent edit
1513:                 * has already been executed, in which case the to be added edit will be
1514:                 * executed immediately, after addition. This is used to handle changes
1515:                 * to the view that are triggered by certain changes of the model. Such
1516:                 * implicit edits may be associated with the view so that they may be
1517:                 * undone and redone correctly, and are stored in the model's global
1518:                 * history together with the parent event as one unit.
1519:                 */
1520:                public void addImplicitEdit(UndoableEdit edit) {
1521:                    // ignore
1522:                }
1523:
1524:                /**
1525:                 * Returns the views that have not changed explicitly, but implicitly
1526:                 * because one of their dependent cells has changed.
1527:                 */
1528:                public CellView[] getViews(GraphLayoutCache view) {
1529:                    return null;
1530:                }
1531:
1532:                /**
1533:                 * Returns the views that have not changed explicitly, but implicitly
1534:                 * because one of their dependent cells has changed.
1535:                 */
1536:                public void putViews(GraphLayoutCache view, CellView[] cellViews) {
1537:                    // ignore
1538:                }
1539:
1540:                /**
1541:                 * Redoes a change.
1542:                 * 
1543:                 * @exception CannotRedoException
1544:                 *                if the change cannot be redone
1545:                 */
1546:                public void redo() throws CannotRedoException {
1547:                    super .redo();
1548:                    updateNext();
1549:                    execute();
1550:                }
1551:
1552:                /**
1553:                 * Undoes a change.
1554:                 * 
1555:                 * @exception CannotUndoException
1556:                 *                if the change cannot be undone
1557:                 */
1558:                public void undo() throws CannotUndoException {
1559:                    super .undo();
1560:                    execute();
1561:                }
1562:
1563:                /**
1564:                 * Execute this edit such that the next invocation to this method will
1565:                 * invert the last execution.
1566:                 */
1567:                public void execute() {
1568:                    for (int i = 0; i < cells.length; i++) {
1569:                        List list = getParentList(cells[i]);
1570:                        if (list != null) {
1571:                            prev[i] = list.indexOf(cells[i]);
1572:                            if (prev[i] >= 0) {
1573:                                list.remove(prev[i]);
1574:                                int n = next[i];
1575:                                if (n == FRONT)
1576:                                    n = list.size();
1577:                                else if (n == BACK)
1578:                                    n = 0;
1579:                                list.add(n, cells[i]);
1580:                                next[i] = prev[i];
1581:                            }
1582:                        }
1583:                    }
1584:                    updateListeners();
1585:                }
1586:
1587:                protected void updateListeners() {
1588:                    fireGraphChanged(DefaultGraphModel.this , this );
1589:                }
1590:
1591:                /**
1592:                 * Returns the list that exclusively contains <code>view</code>.
1593:                 */
1594:                protected List getParentList(Object cell) {
1595:                    List list = null;
1596:                    if (cell instanceof  DefaultMutableTreeNode) {
1597:                        Object parent = ((DefaultMutableTreeNode) cell)
1598:                                .getParent();
1599:                        if (parent instanceof  DefaultGraphCell)
1600:                            list = ((DefaultGraphCell) parent).getChildren();
1601:                        else
1602:                            list = roots;
1603:                    }
1604:                    return list;
1605:                }
1606:
1607:            }
1608:
1609:            //
1610:            // Static Methods
1611:            //
1612:
1613:            /**
1614:             * Returns a deep clone of the specified cell, including all children.
1615:             */
1616:            public static Object cloneCell(GraphModel model, Object cell) {
1617:                Map clones = model.cloneCells(getDescendants(model,
1618:                        new Object[] { cell }).toArray());
1619:                return clones.get(cell);
1620:            }
1621:
1622:            /**
1623:             * Returns a deep clone of the specified cells, including all children.
1624:             */
1625:            public static Object[] cloneCell(GraphModel model, Object[] cells) {
1626:                Map clones = model.cloneCells(getDescendants(model, cells)
1627:                        .toArray());
1628:                for (int i = 0; i < cells.length; i++) {
1629:                    cells[i] = clones.get(cells[i]);
1630:                }
1631:                return cells;
1632:            }
1633:
1634:            /**
1635:             * Helper methods that connects the source of <code>edge</code> to
1636:             * <code>port</code> in <code>model</model>.
1637:             */
1638:            public static void setSourcePort(GraphModel model, Object edge,
1639:                    Object port) {
1640:                model.edit(null, new ConnectionSet(edge, port, true), null,
1641:                        null);
1642:            }
1643:
1644:            /**
1645:             * Helper methods that connects the source of <code>edge</code> to
1646:             * <code>port</code> in <code>model</model>.
1647:             */
1648:            public static void setTargetPort(GraphModel model, Object edge,
1649:                    Object port) {
1650:                model.edit(null, new ConnectionSet(edge, port, false), null,
1651:                        null);
1652:            }
1653:
1654:            /**
1655:             * Returns the source vertex of the edge by calling getParent on getSource
1656:             * on the specified model.
1657:             */
1658:            public static Object getSourceVertex(GraphModel model, Object edge) {
1659:                if (model != null)
1660:                    return model.getParent(model.getSource(edge));
1661:                return null;
1662:            }
1663:
1664:            /**
1665:             * Returns the target vertex of the edge by calling getParent on getTarget
1666:             * on the specified model.
1667:             */
1668:            public static Object getTargetVertex(GraphModel model, Object edge) {
1669:                if (model != null)
1670:                    return model.getParent(model.getTarget(edge));
1671:                return null;
1672:            }
1673:
1674:            /**
1675:             * @return Returns the user object of the given cell. This implementation
1676:             *         checks if the cell is a default mutable tree node and returns
1677:             *         it's user object.
1678:             * 
1679:             * @deprecated Use {@link GraphModel#getValue(Object)} instead.
1680:             */
1681:            public static Object getUserObject(Object cell) {
1682:                if (cell instanceof  DefaultMutableTreeNode)
1683:                    return ((DefaultMutableTreeNode) cell).getUserObject();
1684:                return null;
1685:            }
1686:
1687:            /**
1688:             * Checks whether the cell has at least one child which is not a port. This
1689:             * implementation operates on the model, not taking into account visibility
1690:             * of cells. It returns true for groups regardless of their folded state.
1691:             * 
1692:             * @param cell
1693:             *            the cell to check for being a group
1694:             * @return Returns true if the cell contains at least one cell which is not
1695:             *         a port
1696:             */
1697:            public static boolean isGroup(GraphModel model, Object cell) {
1698:                for (int i = 0; i < model.getChildCount(cell); i++) {
1699:                    if (!model.isPort(model.getChild(cell, i)))
1700:                        return true;
1701:                }
1702:                return false;
1703:            }
1704:
1705:            /**
1706:             * Returns all cells of the model in an array.
1707:             * 
1708:             * @see #getDescendants(GraphModel, Object[])
1709:             * 
1710:             * @return Returns all cells in the model including all descandants.
1711:             */
1712:            public static Object[] getAll(GraphModel model) {
1713:                return getDescendants(model, getRoots(model)).toArray();
1714:            }
1715:
1716:            /**
1717:             * Returns the roots of the specified model as an array. This implementation
1718:             * uses the GraphModel interface in the general case, but if the model is a
1719:             * <code>DefaultGraphModel</code> the performance can be improved to
1720:             * linear time.
1721:             */
1722:            public static Object[] getRoots(GraphModel model) {
1723:                Object[] cells = null;
1724:                if (model != null) {
1725:                    // If model is DefaultGraphModel, we can do a linear time getRoots
1726:                    if (model instanceof  DefaultGraphModel) {
1727:                        cells = ((DefaultGraphModel) model).getRoots()
1728:                                .toArray();
1729:                    } else {
1730:                        cells = new Object[model.getRootCount()];
1731:                        for (int i = 0; i < cells.length; i++) {
1732:                            cells[i] = model.getRootAt(i);
1733:                        }
1734:                    }
1735:                }
1736:                return cells;
1737:            }
1738:
1739:            /**
1740:             * Returns the roots of the specified model as a collection. This implementation
1741:             * uses the GraphModel interface in the general case, but if the model is a
1742:             * <code>DefaultGraphModel</code> the performance can be improved to
1743:             * linear time.
1744:             */
1745:            public static Collection getRootsAsCollection(GraphModel model) {
1746:                Collection cells = null;
1747:                if (model != null) {
1748:                    // If model is DefaultGraphModel, we can do a linear time getRoots
1749:                    if (model instanceof  DefaultGraphModel) {
1750:                        cells = ((DefaultGraphModel) model).getRoots();
1751:                    } else {
1752:                        cells = new LinkedHashSet(model.getRootCount());
1753:                        for (int i = 0; i < cells.size(); i++) {
1754:                            cells.add(model.getRootAt(i));
1755:                        }
1756:                    }
1757:                }
1758:                return cells;
1759:            }
1760:
1761:            /**
1762:             * Returns the roots in <code>cells</code> by checking if their parent is
1763:             * <code>null</code>. This implementation only uses the GraphModel
1764:             * interface. This method never returns null.
1765:             */
1766:            public static Object[] getRoots(GraphModel model, Object[] cells) {
1767:                List roots = new ArrayList();
1768:                if (cells != null) {
1769:                    for (int i = 0; i < cells.length; i++) {
1770:                        if (model.getParent(cells[i]) == null) {
1771:                            roots.add(cells[i]);
1772:                        }
1773:                    }
1774:                }
1775:                return roots.toArray();
1776:            }
1777:
1778:            /**
1779:             * @return Returns the roots of cells, eg. an array that contains no cell
1780:             *         having an ancestor in cells.
1781:             */
1782:            public static Object[] getTopmostCells(GraphModel model,
1783:                    Object[] cells) {
1784:                Set cellSet = new HashSet();
1785:                for (int i = 0; i < cells.length; i++)
1786:                    cellSet.add(cells[i]);
1787:                List parents = new ArrayList();
1788:                for (int i = 0; i < cells.length; i++) {
1789:                    if (!hasAncestorIn(model, cellSet, cells[i]))
1790:                        parents.add(cells[i]);
1791:                }
1792:                return parents.toArray();
1793:            }
1794:
1795:            /**
1796:             * Returns true if the specified child has an ancestor in parents.
1797:             */
1798:            public static boolean hasAncestorIn(GraphModel model, Set parents,
1799:                    Object child) {
1800:                Object parent = model.getParent(child);
1801:                while (parent != null) {
1802:                    if (parents.contains(parent))
1803:                        return true;
1804:                    parent = model.getParent(parent);
1805:                }
1806:                return false;
1807:            }
1808:
1809:            /**
1810:             * Flattens the given array of root cells by adding the roots and their
1811:             * descandants. The resulting set contains all cells, which means it
1812:             * contains branches <strong>and </strong> leafs. Note: This is an iterative
1813:             * implementation. No recursion used. <br>
1814:             * Note: This returns a linked list, for frequent read operations you should
1815:             * turn this into an array, or at least an array list.
1816:             */
1817:            public static List getDescendants(GraphModel model, Object[] cells) {
1818:                if (cells != null) {
1819:                    Stack stack = new Stack();
1820:                    for (int i = cells.length - 1; i >= 0; i--)
1821:                        stack.add(cells[i]);
1822:                    LinkedList result = new LinkedList();
1823:                    while (!stack.isEmpty()) {
1824:                        Object tmp = stack.pop();
1825:                        for (int i = model.getChildCount(tmp) - 1; i >= 0; i--)
1826:                            stack.add(model.getChild(tmp, i));
1827:                        if (tmp != null)
1828:                            result.add(tmp);
1829:                    }
1830:                    return result;
1831:                }
1832:                return null;
1833:            }
1834:
1835:            /**
1836:             * Orders cells so that they reflect the model order.
1837:             */
1838:            public static Object[] order(GraphModel model, Object[] cells) {
1839:                if (cells != null) {
1840:                    Set cellSet = new HashSet();
1841:                    for (int i = 0; i < cells.length; i++)
1842:                        cellSet.add(cells[i]);
1843:                    Stack stack = new Stack();
1844:                    for (int i = model.getRootCount() - 1; i >= 0; i--)
1845:                        stack.add(model.getRootAt(i));
1846:                    LinkedList result = new LinkedList();
1847:                    while (!stack.isEmpty()) {
1848:                        Object tmp = stack.pop();
1849:                        for (int i = model.getChildCount(tmp) - 1; i >= 0; i--)
1850:                            stack.add(model.getChild(tmp, i));
1851:                        if (cellSet.remove(tmp))
1852:                            result.add(tmp);
1853:                    }
1854:                    return result.toArray();
1855:                }
1856:                return null;
1857:            }
1858:
1859:            /**
1860:             * Returns the set of all connected edges to <code>cells</code> or their
1861:             * descendants. The passed-in cells are never returned as part of the result
1862:             * set. This can be used on vertices, edges and ports.
1863:             */
1864:            public static Set getEdges(GraphModel model, Object[] cells) {
1865:                Set result = new HashSet();
1866:                if (cells != null) {
1867:                    // We know the minimum initial capacity of this set is cells.length
1868:                    // We assume the cell has one port at a minimum
1869:                    int setSize = ((int) (cells.length * 1.33) + 1);
1870:                    Set allCells = new HashSet(setSize, 0.75f);
1871:                    for (int i = 0; i < cells.length; i++) {
1872:                        allCells.add(cells[i]);
1873:                    }
1874:                    // Include descendants
1875:                    allCells.addAll(getDescendants(model, cells));
1876:                    if (allCells != null) {
1877:                        Iterator it = allCells.iterator();
1878:                        while (it.hasNext()) {
1879:                            Iterator edges = model.edges(it.next());
1880:                            while (edges.hasNext())
1881:                                result.add(edges.next());
1882:                        }
1883:                        for (int i = 0; i < cells.length; i++)
1884:                            result.remove(cells[i]);
1885:                    }
1886:                }
1887:                return result;
1888:            }
1889:
1890:            /**
1891:             * @return Returns the opposite port or vertex in <code>edge</code>.
1892:             */
1893:            public static Object getOpposite(GraphModel model, Object edge,
1894:                    Object cell) {
1895:                boolean isPort = model.isPort(cell);
1896:                Object source = (isPort) ? model.getSource(edge)
1897:                        : getSourceVertex(model, edge);
1898:                if (cell == source)
1899:                    return (isPort) ? model.getTarget(edge) : getTargetVertex(
1900:                            model, edge);
1901:                else
1902:                    return source;
1903:            }
1904:
1905:            /**
1906:             * Returns true if the given vertices are conntected by a single edge in
1907:             * this document.
1908:             */
1909:            public static boolean containsEdgeBetween(GraphModel model,
1910:                    Object v1, Object v2) {
1911:                Object[] edges = getEdgesBetween(model, v1, v2, false);
1912:                return (edges != null && edges.length > 0);
1913:            }
1914:
1915:            /**
1916:             * Returns the edges between two specified ports or two specified vertices.
1917:             * If directed is true then <code>cell1</code> must be the source of the
1918:             * returned edges. This method never returns null. If there are no edges
1919:             * between the specified cells, then an array of length 0 is returned.
1920:             */
1921:            public static Object[] getEdgesBetween(GraphModel model,
1922:                    Object cell1, Object cell2, boolean directed) {
1923:                boolean isPort1 = model.isPort(cell1);
1924:                boolean isPort2 = model.isPort(cell2);
1925:                ArrayList result = new ArrayList();
1926:                Set edges = DefaultGraphModel.getEdges(model,
1927:                        new Object[] { cell1 });
1928:                Iterator it = edges.iterator();
1929:                while (it.hasNext()) {
1930:                    Object edge = it.next();
1931:                    // TODO: Handle edge groups
1932:                    Object source = (isPort1) ? model.getSource(edge)
1933:                            : getSourceVertex(model, edge);
1934:                    Object target = (isPort2) ? model.getTarget(edge)
1935:                            : getTargetVertex(model, edge);
1936:                    if ((source == cell1 && target == cell2)
1937:                            || (!directed && source == cell2 && target == cell1))
1938:                        result.add(edge);
1939:                }
1940:                return result.toArray();
1941:            }
1942:
1943:            /**
1944:             * Returns the outgoing edges for cell. Cell should be a port or a vertex.
1945:             */
1946:            public static Object[] getOutgoingEdges(GraphModel model,
1947:                    Object cell) {
1948:                return getEdges(model, cell, false);
1949:            }
1950:
1951:            /**
1952:             * Returns the incoming edges for cell. Cell should be a port or a vertex.
1953:             */
1954:            public static Object[] getIncomingEdges(GraphModel model,
1955:                    Object cell) {
1956:                return getEdges(model, cell, true);
1957:            }
1958:
1959:            /**
1960:             * Returns the incoming or outgoing edges for cell. Cell should be a port or
1961:             * a vertex.
1962:             */
1963:            public static Object[] getEdges(GraphModel model, Object cell,
1964:                    boolean incoming) {
1965:                Set edges = DefaultGraphModel.getEdges(model,
1966:                        new Object[] { cell });
1967:                // Base initial capacity on size of set, it can't be any larger
1968:                ArrayList result = new ArrayList(edges.size());
1969:                Iterator it = edges.iterator();
1970:
1971:                while (it.hasNext()) {
1972:                    Object edge = it.next();
1973:                    // TODO: Handle edge groups
1974:                    Object port = (incoming) ? model.getTarget(edge) : model
1975:                            .getSource(edge);
1976:                    Object parent = model.getParent(port);
1977:                    if (port == cell || parent == cell)
1978:                        result.add(edge);
1979:                }
1980:                return result.toArray();
1981:            }
1982:
1983:            /**
1984:             * Returns <code>true</code> if <code>vertex</code> is a valid vertex.
1985:             * 
1986:             * @return <code>true</code> if <code>vertex</code> is a valid vertex.
1987:             */
1988:            public static boolean isVertex(GraphModel model, Object vertex) {
1989:                return (vertex != null && !model.isEdge(vertex) && !model
1990:                        .isPort(vertex));
1991:            }
1992:
1993:            // Serialization support
1994:            private void readObject(ObjectInputStream s) throws IOException,
1995:                    ClassNotFoundException {
1996:                s.defaultReadObject();
1997:                listenerList = new EventListenerList();
1998:                emptyIterator = new EmptyIterator();
1999:            }
2000:
2001:            public static class EmptyIterator implements  Iterator, Serializable {
2002:
2003:                public boolean hasNext() {
2004:                    return false;
2005:                }
2006:
2007:                public Object next() {
2008:                    return null;
2009:                }
2010:
2011:                public void remove() {
2012:                    // nop
2013:                }
2014:            }
2015:
2016:            /**
2017:             * @return the removeEmptyGroups
2018:             */
2019:            public boolean isRemoveEmptyGroups() {
2020:                return removeEmptyGroups;
2021:            }
2022:
2023:            /**
2024:             * @param removeEmptyGroups the removeEmptyGroups to set
2025:             */
2026:            public void setRemoveEmptyGroups(boolean removeEmptyGroups) {
2027:                this.removeEmptyGroups = removeEmptyGroups;
2028:            }
2029:
2030:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.