001: package org.enhydra.jawe.components.graph;
002:
003: import java.awt.Font;
004: import java.awt.Point;
005: import java.awt.Rectangle;
006: import java.awt.event.MouseEvent;
007: import java.lang.reflect.Constructor;
008: import java.util.ArrayList;
009: import java.util.HashMap;
010: import java.util.HashSet;
011: import java.util.Iterator;
012: import java.util.List;
013: import java.util.Map;
014: import java.util.Set;
015: import java.util.Stack;
016:
017: import javax.swing.JComponent;
018: import javax.swing.tree.DefaultMutableTreeNode;
019:
020: import org.enhydra.jawe.JaWEManager;
021: import org.enhydra.jawe.base.xpdlvalidator.ValidationError;
022: import org.enhydra.shark.xpdl.XMLCollectionElement;
023: import org.enhydra.shark.xpdl.XMLElement;
024: import org.enhydra.shark.xpdl.XMLUtil;
025: import org.enhydra.shark.xpdl.XMLValidationError;
026: import org.enhydra.shark.xpdl.elements.Activity;
027: import org.enhydra.shark.xpdl.elements.ActivitySet;
028: import org.enhydra.shark.xpdl.elements.ExtendedAttribute;
029: import org.enhydra.shark.xpdl.elements.Participant;
030: import org.enhydra.shark.xpdl.elements.Transition;
031: import org.enhydra.shark.xpdl.elements.WorkflowProcess;
032: import org.jgraph.JGraph;
033: import org.jgraph.graph.AttributeMap;
034: import org.jgraph.graph.BasicMarqueeHandler;
035: import org.jgraph.graph.CellView;
036: import org.jgraph.graph.GraphConstants;
037: import org.jgraph.graph.GraphLayoutCache;
038: import org.jgraph.graph.GraphModel;
039: import org.jgraph.graph.GraphSelectionModel;
040: import org.jgraph.graph.Port;
041:
042: /**
043: * Standard implementation of JGraph. Represents a WorkflowProcess or ActivitySet graph.
044: * @author Sasa Bojanic
045: */
046: public class Graph extends JGraph {
047:
048: protected WorkflowProcess wp;
049: protected ActivitySet as;
050:
051: /** WorkflowManager that controls various things */
052: protected transient GraphManager graphManager;
053: protected GraphController graphController;
054:
055: public GraphController getGraphController() {
056: return graphController;
057: }
058:
059: /**
060: * Constructs process graph based on a given model.
061: */
062: public Graph(GraphController gc, GraphModel model,
063: BasicMarqueeHandler mh, WorkflowProcess wp) {
064: init(gc, model, mh, wp);
065: graphManager.createWorkflowGraph(wp);
066: }
067:
068: public Graph(GraphController gc, GraphModel model,
069: BasicMarqueeHandler mh, ActivitySet as) {
070: init(gc, model, mh, as);
071: graphManager.createWorkflowGraph(as);
072: }
073:
074: public Graph(GraphModel model, GraphLayoutCache view) {
075: super (model, view);
076: }
077:
078: public Graph(Graph g) {
079: super (g.getModel(), g.getGraphLayoutCache());
080: this .graphController = g.graphController;
081: this .setMarqueeHandler(g.getMarqueeHandler());
082: this .wp = g.getWorkflowProcess();
083: this .as = g.getActivitySet();
084:
085: initGraphBehavior();
086: this .graphManager = g.graphManager;
087: }
088:
089: protected void init(GraphController gc, GraphModel model,
090: BasicMarqueeHandler mh, XMLCollectionElement wpOrAs) {
091: this .graphController = gc;
092: selectionModel = new JaWEGraphSelectionModel(this );
093: setLayout(null);
094: GraphLayoutCache view = new GraphLayoutCache(model,
095: new GraphObjectViewFactory());//HM, JGraph3.4.1
096: setGraphLayoutCache(view);
097: updateUI();
098: if (model == null) {
099: model = new JaWEGraphModel();
100: }
101: setModel(model);
102: this .setMarqueeHandler(mh);
103:
104: if (wpOrAs instanceof WorkflowProcess) {
105: this .wp = (WorkflowProcess) wpOrAs;
106: } else {
107: this .as = (ActivitySet) wpOrAs;
108: this .wp = XMLUtil.getWorkflowProcess(wpOrAs);
109: }
110: initGraphBehavior();
111: this .graphManager = createGraphManager();
112: }
113:
114: // TODO: throw an exception. Maybe make only one instance of GraphManager for all graphs
115: protected GraphManager createGraphManager() {
116: try {
117: String gmc = graphController.getGraphSettings()
118: .getGraphManager();
119: Constructor c = Class.forName(gmc).getConstructor(
120: new Class[] { Graph.class });
121: return (GraphManager) c.newInstance(new Object[] { this });
122: } catch (Exception ex) {
123: return null;
124: }
125: }
126:
127: public GraphManager getGraphManager() {
128: return graphManager;
129: }
130:
131: public WorkflowProcess getWorkflowProcess() {
132: return wp;
133: }
134:
135: public ActivitySet getActivitySet() {
136: return as;
137: }
138:
139: public XMLCollectionElement getXPDLObject() {
140: if (as != null)
141: return as;
142:
143: return wp;
144: }
145:
146: public WorkflowElement selectActivity(Activity act, boolean add) {
147: GraphActivityInterface ga = getGraphManager().getGraphActivity(
148: act);
149: selectElement(ga, add, true);
150: return ga;
151: }
152:
153: public WorkflowElement selectTransition(Transition tra, boolean add) {
154: GraphTransitionInterface gt = getGraphManager()
155: .getGraphTransition(tra);
156: selectElement(gt, add, true);
157: return gt;
158: }
159:
160: public WorkflowElement selectParticipant(Participant par) {
161: GraphParticipantInterface gpar = getGraphManager()
162: .getGraphParticipant(par);
163: selectElement(gpar, false, false);
164: return gpar;
165: }
166:
167: public WorkflowElement selectBubble(ExtendedAttribute ea,
168: boolean add) {
169: GraphBubbleActivityInterface gb = getGraphManager().getBubble(
170: ea);
171: selectElement(gb, add, true);
172: return gb;
173: }
174:
175: public void selectElement(WorkflowElement we, boolean add,
176: boolean toFront) {
177: if (we != null) {
178: if (add) {
179: addSelectionCell(we);
180: } else {
181: setSelectionCell(we);
182: }
183: if (toFront) {
184: getModel().toFront(new Object[] { we });
185: }
186: }
187: }
188:
189: public WorkflowElement getGraphInterface(XMLElement el) {
190: if (el instanceof Activity)
191: return getGraphManager().getGraphActivity((Activity) el);
192:
193: if (el instanceof Transition)
194: return getGraphManager()
195: .getGraphTransition((Transition) el);
196:
197: if (el instanceof Participant)
198: return getGraphManager().getGraphParticipant(
199: (Participant) el);
200:
201: if (el instanceof ExtendedAttribute)
202: return getGraphManager().getBubble((ExtendedAttribute) el);
203:
204: return null;
205: }
206:
207: public void selectElements(Object[] elements, boolean add,
208: boolean toFront) {
209: if (elements != null) {
210: if (add) {
211: addSelectionCells(elements);
212: } else {
213: setSelectionCells(elements);
214: }
215: if (toFront) {
216: getModel().toFront(elements);
217: }
218: }
219: }
220:
221: /**
222: * Overrides Superclass method.
223: */
224: public String convertValueToString(Object value) {
225: if (value instanceof CellView) {
226: value = ((CellView) value).getCell();
227: }
228:
229: if (value instanceof DefaultMutableTreeNode
230: && ((DefaultMutableTreeNode) value).getUserObject() != null
231: && !(value instanceof GraphBubbleActivityInterface)) {
232: if (value instanceof GraphTransitionInterface) {
233: Transition tra = (Transition) ((GraphTransitionInterface) value)
234: .getPropertyObject();
235: if (graphController.getGraphSettings()
236: .shouldShowTransitionNameForCondition()) {
237: return tra.getName();
238: }
239: return tra.getCondition().toValue();
240: }
241: return value.toString();
242: } else if (value != null) {
243: return value.toString();
244: }
245: return null;
246: }
247:
248: /**
249: * Finds the topmost Participant at specified location.
250: */
251: public Object getFirstParticipantForLocation(int x, int y) {
252: x /= scale;
253: y /= scale; // FIX: Consistency with other methods?
254: CellView[] cells = getOrderedAllSelectableCells();
255: if (cells != null) {
256: Rectangle r = new Rectangle(x - tolerance, y - tolerance,
257: 2 * tolerance, 2 * tolerance);
258: // Iterate through cells and find first Participant at
259: // if current is traversed. Cache first cell.
260: for (int i = 0; i < cells.length; i++) {
261: if (cells[i] instanceof GraphParticipantViewInterface) {
262: boolean intersects = cells[i].getBounds()
263: .intersects(r);
264: if (intersects) {
265: return cells[i].getCell();
266: }
267: }
268: }
269: }
270:
271: return null;
272: }
273:
274: /**
275: * Modified from original to support all views
276: */
277: public CellView getNextViewAt(CellView current, double x, double y) {//HM, JGraph3.4.1
278: CellView[] sel = getOrderedAllSelectableCells();
279: CellView cell = getNextViewAt(sel, current, x, y);
280: return cell;
281: }
282:
283: /**
284: * Modified from original to suite our needs. This method makes a Participant
285: * to be selected only when it's name part is pressed, and to give it's
286: * tooltip only when you want to insert some cells in it.
287: */
288: public CellView getNextViewAt(CellView[] cells, CellView c,
289: double x, double y) {//HM, JGraph3.4.1
290: if (cells != null) {
291:
292: Rectangle r = new Rectangle((int) x - tolerance, (int) y
293: - tolerance, 2 * tolerance, 2 * tolerance);//HM, JGraph3.4.1
294: // Iterate through cells and switch to active
295: // if current is traversed. Cache first cell.
296: CellView first = null;
297: boolean active = (c == null);
298:
299: for (int i = 0; i < cells.length; i++) {
300: boolean intersects = false;
301: boolean wholeArea = true;
302: GraphMarqueeHandler mh = (GraphMarqueeHandler) marquee;
303: if (mh.isSelectButtonSelected()
304: || mh.isTransitionButtonSelected()) {
305: wholeArea = false;
306: }
307: if ((cells[i] instanceof GraphParticipantViewInterface)
308: && wholeArea) {
309: intersects = cells[i].getBounds().intersects(r);
310: } else {
311: intersects = cells[i].intersects(this , r);
312: }
313:
314: if (intersects) {
315: if (active) {
316: return cells[i];
317: } else if (first == null) {
318: first = cells[i];
319: }
320: active = active | (cells[i] == c);
321: }
322: }
323: return first;
324: }
325: return null;
326: }
327:
328: /**
329: * This method gets all selectable views and puts it in an order that suites to
330: * our needs (first comes activities and transitions(edges), and then Participants sorted
331: * by level - root Participants comes last)
332: */
333: private CellView[] getOrderedAllSelectableCells() {
334: // Get Roots in View Order
335: CellView[] views = graphLayoutCache.getRoots();
336: // Add Roots to Stack
337: Stack s = new Stack();
338: for (int i = 0; i < views.length; i++) {
339: s.add(views[i]);
340: }
341: java.util.List result = new ArrayList();
342: // Traverse All Children In View Order
343: while (!s.isEmpty()) {
344: CellView view = (CellView) s.pop();
345: Object cell = view.getCell();
346: // Add To List if it is not a port or forbidden object
347: if (!(cell instanceof Port)) {// && !(cell instanceof SubflowPort)) {
348: result.add(view);
349: }
350: // Add Children to Stack
351: CellView[] children = view.getChildViews();
352: for (int i = 0; i < children.length; i++) {
353: s.add(children[i]);
354: }
355: }
356: // Order so that all activities comes first, after that Participants in ordered view
357:
358: // first iteration - separating Participants and others
359: java.util.List activitiesAndEdges = new ArrayList();
360: java.util.List participants = new ArrayList();
361: Iterator it = result.iterator();
362: while (it.hasNext()) {
363: CellView cv = (CellView) it.next();
364: if (cv.getCell() instanceof GraphParticipantInterface) {
365: participants.add(cv);
366: } else {
367: activitiesAndEdges.add(cv);
368: }
369: }
370:
371: // second iteration - order, first adding activities & edges and then
372: // Participants in reversed order: it must be done that way because the
373: // child views of Participants (activities) that had focus more recently
374: // has higher number and are placed closer to the begining of
375: // activitiesAndEdges set, but on contrary, Participants that has higher
376: // depth (and should have focus before their parents) are placed closer
377: // to the end of Participants set
378: int i = -1;
379: int j = participants.size() + activitiesAndEdges.size();
380: CellView[] tmp = new CellView[j];
381:
382: it = activitiesAndEdges.iterator();
383: while (it.hasNext()) {
384: tmp[++i] = (CellView) it.next();
385: }
386:
387: it = participants.iterator();
388: while (it.hasNext()) {
389: tmp[--j] = (CellView) it.next();
390: }
391:
392: return tmp;
393: }
394:
395: /**
396: * Only for debugging purpose.
397: */
398: public void printOrderedAllSelectables() {
399: CellView[] sel = getOrderedAllSelectableCells();
400: for (int i = 0; i < sel.length; i++)
401: System.out.println("view" + i + "=" + sel[i].getCell());
402: }
403:
404: /**
405: * Overrides <code>JComponent</code>'s <code>getToolTipText</code>
406: * method in order to allow the graph controller to create a tooltip
407: * for the topmost cell under the mousepointer. This differs from JTree
408: * where the renderers tooltip is used.
409: * <p>
410: * NOTE: For <code>JGraph</code> to properly display tooltips of its
411: * renderers, <code>JGraph</code> must be a registered component with the
412: * <code>ToolTipManager</code>. This can be done by invoking
413: * <code>ToolTipManager.sharedInstance().registerComponent(graph)</code>.
414: * This is not done automatically!
415: * @param event the <code>MouseEvent</code> that initiated the
416: * <code>ToolTip</code> display
417: * @return a string containing the tooltip or <code>null</code>
418: * if <code>event</code> is null
419: */
420: public String getToolTipText(MouseEvent event) {
421: if (event != null) {
422: Object cell;
423: // if activity or Participant is to be inserted, show
424: // underlying Participant, else show other
425: GraphMarqueeHandler mh = (GraphMarqueeHandler) marquee;
426: Point p = (Point) fromScreen(event.getPoint());
427: if (!(mh.isSelectButtonSelected() || mh
428: .isTransitionButtonSelected())) {
429: cell = getFirstParticipantForLocation((int) p.getX(),
430: (int) p.getY());
431: } else {
432: cell = getFirstCellForLocation(p.getX(), p.getY());
433: }
434: if (cell != null) {
435: String s = convertValueToString(cell);
436: if (cell instanceof WorkflowElement) {
437: s = ((WorkflowElement) cell).getTooltip();
438: }
439: return s;
440: }
441: }
442: return null;
443: }
444:
445: public boolean validateAgainsXPDLSchema() {
446: return true;
447: }
448:
449: // /**
450: // * Reacts upon the XML element change by setting isModified flag
451: // * of PackageEditor if needed.
452: // */
453: // public void xmlElementChanged (XMLElement el) {
454: // if (el instanceof org.enhydra.shark.xpdl.elements.Activity) {
455: // editor.getStatusBar().updateMessage();
456: // }
457: // }
458: //
459:
460: public void initGraphBehavior() {
461: setHandleSize(4);
462: setTolerance(4);
463: setSizeable(false);
464: setMoveable(!getXPDLObject().isReadOnly());
465: setDisconnectable(true);
466: setDisconnectOnMove(false);
467: setAntiAliased(true);
468: setAutoscrolls(true);
469: selectionModel
470: .setSelectionMode(GraphSelectionModel.MULTIPLE_GRAPH_SELECTION);
471: refreshGraphConfiguration();
472:
473: }
474:
475: public void refreshGraphConfiguration() {
476: GraphSettings gval = GraphUtilities.getGraphController()
477: .getGraphSettings();
478: boolean gs = gval.shouldShowGrid();
479: setGridEnabled(gs);
480: setGridVisible(gs);
481: setGridSize(gval.getGridSize());
482: setBackground(gval.getBackgroundColor());
483: setHighlightColor(gval.getSelectedActivityColor());
484: setGridColor(gval.getGridColor());
485: setHandleColor(gval.getHandleColor());
486: setMarqueeColor(gval.getMarqueeColor());
487: setFontSize();
488: // ((JaWEMarqueeHandler)getMarqueeHandler()).enableBubblesButtons(JaWEConfig.getInstance().getUseBubblesStatus());
489: // updateStartEndBubbles();
490: }
491:
492: protected void setFontSize() {
493: // boolean isModified=JaWE.getInstance().isModified();
494: List cellList = JaWEGraphModel.getAllCellsInModel(getModel());
495: if (cellList == null)
496: return;
497: //Filter ports out
498: java.util.List list = new ArrayList();
499: for (Iterator i = cellList.iterator(); i.hasNext();) {
500: Object cell = i.next();
501: if (!(cell instanceof Port)) {
502: list.add(cell);
503: }
504: }
505: Object[] cells = list.toArray();
506:
507: String fntn = JaWEManager.getFontName();
508: int fntsize = graphController.getGraphSettings()
509: .getGraphFontSize();
510: javax.swing.plaf.FontUIResource f;
511: try {
512: try {
513: f = new javax.swing.plaf.FontUIResource(fntn,
514: Font.PLAIN, fntsize);
515: } catch (Exception ex) {
516: f = new javax.swing.plaf.FontUIResource("Label.font",
517: Font.PLAIN, fntsize);
518: }
519: Map nested = new HashMap();
520: for (int i = 0; i < cells.length; i++) {
521: CellView view = getGraphLayoutCache().getMapping(
522: cells[i], false);
523: if (view != null) {
524: Font font = GraphConstants.getFont(view
525: .getAllAttributes());
526: if (font.getSize() == fntsize) {
527: return;
528: }
529: AttributeMap attr = new AttributeMap();
530: GraphConstants.setFont(attr, f.deriveFont(fntsize));
531: nested.put(cells[i], attr);
532: }
533: }
534: //getGraphLayoutCache().edit(nested, null, null, null);
535: //graphModel.edit(nested,null,null,null);
536: ((JaWEGraphModel) graphModel).editFonts(nested);
537: } catch (Exception ex) {
538:
539: }
540: }
541:
542: /**
543: * Overrides super method - don't need to waste a time for this.
544: */
545: public static void addSampleData(GraphModel model) {
546: return;
547: }
548:
549: /**
550: * Notification from the <code>UIManager</code> that the L&F has changed.
551: * Replaces the current UI object with the latest version from the
552: * <code>UIManager</code>. Subclassers can override this to support
553: * different GraphUIs.
554: * @see JComponent#updateUI
555: *
556: */
557: public void updateUI() {
558: setUI(new JaWEGraphUI());
559: invalidate();
560: }
561:
562: public String toString() {
563: XMLCollectionElement xpdlo = getXPDLObject();
564: if (xpdlo != null) {
565: return JaWEManager.getInstance().getDisplayNameGenerator()
566: .getDisplayName(xpdlo);
567: }
568: return "";
569: }
570:
571: public List checkConnections(boolean fullCheck) {
572: boolean wellConnected = true;
573: List verrors = new ArrayList();
574:
575: // check start's and end's connections
576: Set icStarts = getImproperlyConnectedStarts(fullCheck);
577: if (icStarts.size() > 0) {
578: wellConnected = false;
579: for (Iterator i = icStarts.iterator(); i.hasNext();) {
580: GraphActivityInterface s = (GraphActivityInterface) i
581: .next();
582: ValidationError ve = null;
583: if (s instanceof GraphBubbleActivityInterface) {
584: ve = new ValidationError(
585: new XMLValidationError(
586: XMLValidationError.TYPE_ERROR,
587: XMLValidationError.SUB_TYPE_CONNECTION,
588: getGraphController()
589: .getSettings()
590: .getLanguageDependentString(
591: "ErrorConnectionToStartingActivityIsMissing"),
592: "", s.getPropertyObject()));
593: } else {
594: ve = new ValidationError(
595: new XMLValidationError(
596: XMLValidationError.TYPE_ERROR,
597: XMLValidationError.SUB_TYPE_CONNECTION,
598: getGraphController()
599: .getSettings()
600: .getLanguageDependentString(
601: "ErrorIncomingTransitionOrConnectionFromStartBubbleIsMissing"),
602: "", s.getPropertyObject()));
603: }
604: verrors.add(ve);
605: if (!(wellConnected || fullCheck)) {
606: break;
607: }
608:
609: }
610: }
611:
612: if (fullCheck || wellConnected) {
613: Set icEnds = getImproperlyConnectedEnds(fullCheck);
614: if (icEnds.size() > 0) {
615: wellConnected = false;
616: for (Iterator i = icEnds.iterator(); i.hasNext();) {
617: GraphActivityInterface e = (GraphActivityInterface) i
618: .next();
619: ValidationError ve = null;
620: if (e instanceof GraphBubbleActivityInterface) {
621: if (e.getReferencingActivities().size() == 0) {
622: ve = new ValidationError(
623: new XMLValidationError(
624: XMLValidationError.TYPE_ERROR,
625: XMLValidationError.SUB_TYPE_CONNECTION,
626: getGraphController()
627: .getSettings()
628: .getLanguageDependentString(
629: "ErrorConnectionFromEndingActivityIsMissing"),
630: "", e.getPropertyObject()));
631: } else {
632: ve = new ValidationError(
633: new XMLValidationError(
634: XMLValidationError.TYPE_ERROR,
635: XMLValidationError.SUB_TYPE_CONNECTION,
636: getGraphController()
637: .getSettings()
638: .getLanguageDependentString(
639: "ErrorNotConnectedToEndingActivity"),
640: "", e.getPropertyObject()));
641: }
642: } else {
643: ve = new ValidationError(
644: new XMLValidationError(
645: XMLValidationError.TYPE_ERROR,
646: XMLValidationError.SUB_TYPE_CONNECTION,
647: getGraphController()
648: .getSettings()
649: .getLanguageDependentString(
650: "ErrorOutgoingTransitionOrConnectionToEndBubbleIsMissing"),
651: "", e.getPropertyObject()));
652:
653: }
654: verrors.add(ve);
655: if (!(wellConnected || fullCheck)) {
656: break;
657: }
658: }
659: }
660: }
661:
662: return verrors;
663: }
664:
665: public Set getImproperlyConnectedStarts(boolean fullCheck) {
666: Set icStarts = new HashSet();
667:
668: List allGraphActivities = JaWEGraphModel
669: .getAllActivitiesInModel(graphModel);
670: if (allGraphActivities != null) {
671: Iterator it = allGraphActivities.iterator();
672: while (it.hasNext()) {
673: GraphActivityInterface gact = (GraphActivityInterface) it
674: .next();
675: if (gact instanceof GraphBubbleActivityInterface
676: && ((GraphBubbleActivityInterface) gact)
677: .isStart()) {
678: if (gact.getReferencedActivities().size() == 0) {
679: icStarts.add(gact);
680: if (!fullCheck) {
681: break;
682: }
683: }
684: } else if (!(gact instanceof GraphBubbleActivityInterface)) {
685: Set incomingTrans = gact.getReferencingActivities();
686: if (incomingTrans.size() == 0) {
687: icStarts.add(gact);
688: if (!fullCheck) {
689: break;
690: }
691: }
692: // else if (incomingTrans.size()==1) {
693: // if (Utils.hasCircularTransitions(incomingTrans)) {
694: // icStarts.add(act);
695: // if (!fullCheck) {
696: // break;
697: // }
698: // }
699: // }
700: }
701: }
702: }
703: return icStarts;
704: }
705:
706: public Set getImproperlyConnectedEnds(boolean fullCheck) {
707: Set icEnds = new HashSet();
708:
709: List allGraphActivities = JaWEGraphModel
710: .getAllActivitiesInModel(graphModel);
711: if (allGraphActivities != null) {
712: Iterator it = allGraphActivities.iterator();
713: while (it.hasNext()) {
714: GraphActivityInterface gact = (GraphActivityInterface) it
715: .next();
716: if (gact instanceof GraphBubbleActivityInterface
717: && !((GraphBubbleActivityInterface) gact)
718: .isStart()) {
719: Set incT = gact.getReferencingActivities();
720: if (incT.size() == 0) {
721: icEnds.add(gact);
722: if (!fullCheck) {
723: break;
724: }
725: }
726: // else if (incT.size()==1) {
727: // Transition t=(Transition)incT.toArray()[0];
728: // Activity a=(Activity)((DefaultPort)t.getSource()).getParent();
729: // Set eas=XMLUtil.getEndingActivities((XMLCollectionElement)getXPDLObject());
730: // if (!eas.contains(a.getPropertyObject())) {
731: // icEnds.add(act);
732: // if (!fullCheck) {
733: // break;
734: // }
735: // }
736: // }
737: } else if (!(gact instanceof GraphBubbleActivityInterface)) {
738: Set excTrans = XMLUtil
739: .getExceptionalOutgoingTransitions((Activity) gact
740: .getPropertyObject());
741: Set outgoingTrans = gact.getReferencedActivities();
742: if (outgoingTrans.size() == 0
743: || (outgoingTrans.size() == 1 && excTrans
744: .size() > 0)) {
745: icEnds.add(gact);
746: if (!fullCheck) {
747: break;
748: }
749: }
750: // if (outgoingTrans.size()==1) {
751: // if (Utils.hasCircularTransitions(outgoingTrans)) {
752: // icEnds.add(act);
753: // if (!fullCheck) {
754: // break;
755: // }
756: // }
757: // }
758: }
759: }
760: }
761:
762: return icEnds;
763: }
764:
765: // TO AVOID MEMORY LEAK -> RENDERERS HOLD A REFERENCE TO GRAPHS
766: public void clearXPDLObjectReferences() {
767: // Object[] elem = JaWEGraphModel.getAll(graphModel);
768: // graphModel.remove(elem);
769: // setUI(null);
770: // wp=null;
771: // as=null;
772: // graphLayoutCache=null;
773: // graphModel=null;
774: // selectionModel=null;
775: DefaultGraphActivityView.renderers.clear();
776: // DefaultGraphBubbleActivityView.renderers.clear();
777: DefaultGraphParticipantView.renderers.clear();
778: DefaultGraphTransitionView.renderers.clear();
779: DefaultGraphPortView.renderers.clear();
780: }
781:
782: }
|