Source Code Cross Referenced for JaWEGraphModel.java in  » Workflow-Engines » JaWE » org » enhydra » jawe » components » 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 » Workflow Engines » JaWE » org.enhydra.jawe.components.graph 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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