1
2
3
4
5
6 package net.kwfgrid.gwui.graphview;
7
8 import net.kwfgrid.gwui.util.*;
9 import net.kwfgrid.gworkflowdl.protocol.structure.*;
10 import net.kwfgrid.gworkflowdl.structure.*;
11
12 import java.util.*;
13 import javax.swing.*;
14 import java.beans.*;
15
16 import org.apache.log4j.Logger;
17
18 import org.glassbox.gui.Visible;
19 import org.glassbox.graphview.GGraphPane;
20
21 import de.fzi.wim.guibase.graphview.layout.Layouter;
22 import de.fzi.wim.guibase.graphview.graph.Graph;
23 import de.fzi.wim.guibase.graphview.graph.Node;
24
25 /***
26 A view for the workflow graph.
27 */
28 public class WorkflowGraphView implements IStructureListenerExt, Visible, PropertyChangeListener {
29 private static final Logger logger = Logger.getLogger(WorkflowGraphView.class);
30
31 private ProtocolWorkflow _workflow;
32 private GGraphPane _graphpane;
33 /*** Place/Transition -> Node */
34 private HashMap _nodestoadd;
35 private List _nodestoremove;
36 /*** PlaceID/TransitionID -> Node */
37 private HashMap _tnodestoremove, _pnodestoremove;
38 private List _edgestoadd, _edgestoremove;
39 /*** (PlaceID, TransitionID) -> Edge */
40 private HashMapOfMaps _readedgestoremove, _inedgestoremove, _outedgestoremove;
41 private WorkflowGraphAnalyzer _analyzer;
42 private Layouter _layouter;
43 private LayoutFactory _layoutfactory;
44
45 public WorkflowGraphView(WorkflowGraphAnalyzer analyzer, LayoutFactory layoutfactory) {
46 _workflow = null;
47 _graphpane = null;
48 _edgestoadd = new LinkedList();
49 _edgestoremove = new LinkedList();
50 _nodestoadd = new HashMap();
51 _nodestoremove = new LinkedList();
52 _tnodestoremove = new HashMap();
53 _pnodestoremove = new HashMap();
54 _readedgestoremove = new HashMapOfMaps();
55 _inedgestoremove = new HashMapOfMaps();
56 _outedgestoremove = new HashMapOfMaps();
57 _layouter = null;
58 _analyzer = analyzer;
59 _layouter = null;
60 if (layoutfactory == null) layoutfactory = NullLayoutFactory.getInstance();
61 _layoutfactory = layoutfactory;
62 }
63
64
65
66
67
68 /***
69 Set the displayed workflow.
70 */
71 public void setWorkflow(ProtocolWorkflow workflow) {
72 logger.debug("New workflow instance set: "+workflow);
73
74 if (_workflow!=null) {
75 _workflow.removeStructureListener(this);
76 }
77
78 _workflow = workflow;
79
80 if (_workflow == null) {
81 _graphpane.setGraph(null);
82 } else {
83 _workflow.addStructureListener(this);
84 buildNewGraph();
85 }
86 }
87
88 /***
89 Set the <code>LayoutFactory</code> used by this view.
90 This will immediately create a new layout based on the new factory.
91 */
92 public void setLayoutFactory(LayoutFactory lfact) {
93 if (lfact == null) lfact = NullLayoutFactory.getInstance();
94 _layoutfactory = lfact;
95
96 }
97
98 /***
99 Dispose this view.
100 */
101 public void dispose() {
102 setWorkflow(null);
103 }
104
105 /***
106 Get the GraphPane used for painting.
107 */
108 public GGraphPane getGraphPane() {
109 return (GGraphPane)getView();
110 }
111
112 /***
113 Get the graph.
114 */
115 public WorkflowGraph getGraph() {
116 return (WorkflowGraph)getGraphPane().getGraph();
117 }
118
119
120
121
122
123 public void propertyChange(PropertyChangeEvent e) {
124 if ("graph".equals(e.getPropertyName())) {
125 notifyNewGraph((Graph)e.getNewValue());
126 }
127 }
128
129 /***
130 Notify the instance that a new graph should be layouted.
131 */
132 protected void notifyNewGraph(Graph graph) {
133 if (_layouter != null) {
134 _layouter.stop();
135 _layouter = null;
136 }
137 if (graph != null) {
138
139 _layouter = new Layouter(_layoutfactory.createLayoutStrategy(graph));
140 _layouter.start();
141 }
142 }
143
144
145
146
147
148 private boolean isTransition(String namespace, String name) {
149 return ProtocolTransition.NAME.equals(name) && ProtocolTransition.NAMESPACE.equals(namespace);
150 }
151
152 private boolean isPlace(String namespace, String name) {
153 return ProtocolPlace.NAME.equals(name) && ProtocolPlace.NAMESPACE.equals(namespace);
154 }
155
156 private boolean isReadEdge(String namespace, String name) {
157 return ProtocolEdge.NAME_READPLACE.equals(name) && ProtocolEdge.NAMESPACE.equals(namespace);
158 }
159
160 private boolean isWriteEdge(String namespace, String name) {
161 return ProtocolEdge.NAME_WRITEPLACE.equals(name) && ProtocolEdge.NAMESPACE.equals(namespace);
162 }
163
164 private boolean isInEdge(String namespace, String name) {
165 return ProtocolEdge.NAME_INPUTPLACE.equals(name) && ProtocolEdge.NAMESPACE.equals(namespace);
166 }
167
168 private boolean isOutEdge(String namespace, String name) {
169 return ProtocolEdge.NAME_OUTPUTPLACE.equals(name) && ProtocolEdge.NAMESPACE.equals(namespace);
170 }
171
172 private ProtocolTransition isChildOfTransition(IStructureObject parent) {
173 while (parent instanceof IChildObject) {
174 if (parent instanceof Transition) return (ProtocolTransition)parent;
175 parent = ((IChildObject)parent).getParent();
176 }
177 return null;
178 }
179
180 private ProtocolPlace isChildOfPlace(IStructureObject parent) {
181 while (parent instanceof IChildObject) {
182 if (parent instanceof Place) return (ProtocolPlace)parent;
183 parent = ((IChildObject)parent).getParent();
184 }
185 return null;
186 }
187
188 private ProtocolEdge isChildOfReadEdge(IStructureObject parent) {
189 while (parent instanceof IChildObject) {
190 if (parent instanceof Edge) {
191 ProtocolEdge edge = (ProtocolEdge)parent;
192 Transition transition = (Transition)edge.getParent();
193 if (edge == transition.getReadEdge(edge.getPlaceID())) {
194 return edge;
195 } else {
196 return null;
197 }
198 }
199 parent = ((IChildObject)parent).getParent();
200 }
201 return null;
202 }
203
204 private ProtocolEdge isChildOfInEdge(IStructureObject parent) {
205 while (parent instanceof IChildObject) {
206 if (parent instanceof Edge) {
207 ProtocolEdge edge = (ProtocolEdge)parent;
208 Transition transition = (Transition)edge.getParent();
209 if (edge == transition.getInEdge(edge.getPlaceID())) {
210 return edge;
211 } else {
212 return null;
213 }
214 }
215 parent = ((IChildObject)parent).getParent();
216 }
217 return null;
218 }
219
220 private ProtocolEdge isChildOfOutEdge(IStructureObject parent) {
221 while (parent instanceof IChildObject) {
222 if (parent instanceof Edge) {
223 ProtocolEdge edge = (ProtocolEdge)parent;
224 Transition transition = (Transition)edge.getParent();
225 if (edge == transition.getOutEdge(edge.getPlaceID())) return edge;
226 else return null;
227 }
228 parent = ((IChildObject)parent).getParent();
229 }
230 return null;
231 }
232
233
234
235
236
237 private void buildNewGraph() {
238 WorkflowGraph current = getGraph();
239 GraphBuilder graphbuilder = null;
240 if (current!=null) {
241 graphbuilder = new GraphBuilder2(current, _workflow);
242 } else {
243 graphbuilder = new GraphBuilder(_workflow);
244 }
245 graphbuilder.build();
246 current = graphbuilder.getGraph();
247 _analyzer.updateWorkflowGraph(current);
248 Iterator nodes = current.getNodes().iterator(); while (nodes.hasNext()) {
249 Node node = (Node)nodes.next();
250 node.setLocation(Integer.MAX_VALUE, Integer.MAX_VALUE);
251 if (node instanceof TransitionNode)
252 _analyzer.updateTransitionNode((TransitionNode)node);
253 else
254 _analyzer.updatePlaceNode((PlaceNode)node);
255 }
256 Iterator edges = current.getEdges().iterator(); while (edges.hasNext()) {
257 ArcEdge edge = (ArcEdge)edges.next();
258 if (edge instanceof ReadEdge)
259 _analyzer.updateReadEdge((ReadEdge)edge);
260 else if (edge instanceof InEdge)
261 _analyzer.updateInEdge((InEdge)edge);
262 else
263 _analyzer.updateOutEdge((OutEdge)edge);
264 }
265 getGraphPane().setGraph(current);
266 }
267
268
269
270 private TransitionNode getTransitionNode(Transition t) {
271 TransitionNode node = (TransitionNode)_nodestoadd.get(t);
272 if (node == null) node = getGraph().getTransitionNode(t);
273 return node;
274 }
275
276 private PlaceNode getPlaceNode(Place p) {
277 PlaceNode node = (PlaceNode)_nodestoadd.get(p);
278 if (node == null) node = getGraph().getPlaceNode(p);
279 return node;
280 }
281
282
283
284 private void addTransitionNode(Transition transition) {
285 TransitionNode removednode = (TransitionNode)_tnodestoremove.remove(transition.getID());
286 if (removednode != null) {
287 removednode.setTransition(transition);
288 _analyzer.updateTransitionNode(removednode);
289 } else {
290 TransitionNode tn = new TransitionNode(transition);
291 tn.setLocation(Integer.MIN_VALUE, Integer.MIN_VALUE);
292 _analyzer.updateTransitionNode(tn);
293 _nodestoadd.put(transition, tn);
294 }
295 }
296
297 private void addPlaceNode(Place place) {
298 PlaceNode removednode = (PlaceNode)_pnodestoremove.remove(place.getID());
299 if (removednode != null) {
300 removednode.setPlace(place);
301 _analyzer.updatePlaceNode(removednode);
302 } else {
303 PlaceNode pn = new PlaceNode(place);
304 pn.setLocation(Integer.MIN_VALUE, Integer.MIN_VALUE);
305 _analyzer.updatePlaceNode(pn);
306 _nodestoadd.put(place, pn);
307 }
308 }
309
310 private void addTransitionNodes(List transitions) {
311 Iterator i = transitions.iterator(); while (i.hasNext()) {
312 addTransitionNode((Transition)i.next());
313 }
314 }
315
316 private void addPlaceNodes(List places) {
317 Iterator i = places.iterator(); while (i.hasNext()) {
318 addPlaceNode((Place)i.next());
319 }
320 }
321
322
323
324 private void removeTransitionNodes(List transitions) {
325 Iterator i = transitions.iterator(); while (i.hasNext()) {
326 Transition t = (Transition)i.next();
327 _tnodestoremove.put(t.getID(), getGraph().getTransitionNode(t));
328 }
329 }
330
331 private void removePlaceNodes(List places) {
332 Iterator i = places.iterator(); while (i.hasNext()) {
333 Place p = (Place)i.next();
334 _pnodestoremove.put(p.getID(), getGraph().getPlaceNode(p));
335 }
336 }
337
338
339
340 private void addReadEdge(Edge arc, TransitionNode tonode) {
341 ReadEdge removededge = (ReadEdge)_readedgestoremove.remove(arc.getPlace().getID(), tonode.getTransition().getID());
342 if (removededge != null) {
343 removededge.setArc(arc);
344 _analyzer.updateReadEdge(removededge);
345 } else {
346 Place from = arc.getPlace();
347 ReadEdge ae = new ReadEdge(getPlaceNode(from), tonode, arc);
348 _analyzer.updateReadEdge(ae);
349 _edgestoadd.add(ae);
350 }
351 }
352
353 private void addInEdge(Edge arc, TransitionNode tonode) {
354 InEdge removededge = (InEdge)_inedgestoremove.remove(arc.getPlace().getID(), tonode.getTransition().getID());
355 if (removededge != null) {
356 removededge.setArc(arc);
357 _analyzer.updateInEdge(removededge);
358 } else {
359 Place from = arc.getPlace();
360 InEdge ae = new InEdge(getPlaceNode(from), tonode, arc);
361 _analyzer.updateInEdge(ae);
362 _edgestoadd.add(ae);
363 }
364 }
365
366 private void addOutEdge(Edge arc, TransitionNode fromnode) {
367 OutEdge removededge = (OutEdge)_outedgestoremove.remove(arc.getPlace().getID(), fromnode.getTransition().getID());
368 if (removededge != null) {
369 removededge.setArc(arc);
370 _analyzer.updateOutEdge(removededge);
371 } else {
372 Place to = arc.getPlace();
373 OutEdge ae = new OutEdge(fromnode, getPlaceNode(to), arc);
374 _analyzer.updateOutEdge(ae);
375 _edgestoadd.add(ae);
376 }
377 }
378
379 private void addReadEdges(List edges, Transition to) {
380 TransitionNode tonode = getTransitionNode(to);
381 Iterator i = edges.iterator(); while (i.hasNext()) {
382 addReadEdge((Edge)i.next(), tonode);
383 }
384 }
385
386 private void addReadEdges(Transition to) {
387 Edge[] edges = to.getReadEdges();
388 TransitionNode tonode = getTransitionNode(to);
389 for (int i = 0; i<edges.length; i++) {
390 addReadEdge(edges[i], tonode);
391 }
392 }
393
394 private void addInEdges(List edges, Transition to) {
395 TransitionNode tonode = getTransitionNode(to);
396 Iterator i = edges.iterator(); while (i.hasNext()) {
397 addInEdge((Edge)i.next(), tonode);
398 }
399 }
400
401 private void addInEdges(Transition to) {
402 Edge[] edges = to.getInEdges();
403 TransitionNode tonode = getTransitionNode(to);
404 for (int i = 0; i<edges.length; i++) {
405 addInEdge(edges[i], tonode);
406 }
407 }
408
409 private void addOutEdges(List edges, Transition from) {
410 TransitionNode fromnode = getTransitionNode(from);
411 Iterator i = edges.iterator(); while (i.hasNext()) {
412 addOutEdge((Edge)i.next(), fromnode);
413 }
414 }
415
416 private void addOutEdges(Transition from) {
417 Edge[] edges = from.getOutEdges();
418 TransitionNode fromnode = getTransitionNode(from);
419 for (int i = 0; i<edges.length; i++) {
420 addOutEdge(edges[i], fromnode);
421 }
422 }
423
424 private void addEdges(List transitions) {
425 Iterator it = transitions.iterator(); while (it.hasNext()) {
426 Transition t = (Transition)it.next();
427 addReadEdges(t);
428 addInEdges(t);
429 addOutEdges(t);
430 }
431 }
432
433
434
435 private void removeEdges(List transitions) {
436 Iterator it = transitions.iterator(); while (it.hasNext()) {
437 Transition t = (Transition)it.next();
438 Edge[] e = t.getReadEdges();
439 for (int i=0; i<e.length; i++) {
440 ArcEdge ae = getGraph().getReadEdge(e[i].getPlace(), t);
441 _readedgestoremove.put(e[i].getPlace().getID(), t.getID(), ae);
442 }
443 e = t.getInEdges();
444 for (int i=0; i<e.length; i++) {
445 ArcEdge ae = getGraph().getInEdge(e[i].getPlace(), t);
446 _inedgestoremove.put(e[i].getPlace().getID(), t.getID(), ae);
447 }
448 e = t.getOutEdges();
449 for (int i=0; i<e.length; i++) {
450 ArcEdge ae = getGraph().getOutEdge(t, e[i].getPlace());
451 _outedgestoremove.put(e[i].getPlace().getID(), t.getID(), ae);
452 }
453 }
454 }
455
456 private void removeReadEdges(List edges, Transition to) {
457 Iterator i = edges.iterator(); while (i.hasNext()) {
458 Edge e = (Edge)i.next();
459 Place from = e.getPlace();
460 _readedgestoremove.put(e.getPlace().getID(), to.getID(), getGraph().getReadEdge(from, to));
461 }
462 }
463
464 private void removeInEdges(List edges, Transition to) {
465 Iterator i = edges.iterator(); while (i.hasNext()) {
466 Edge e = (Edge)i.next();
467 Place from = e.getPlace();
468 _inedgestoremove.put(e.getPlace().getID(), to.getID(), getGraph().getInEdge(from, to));
469 }
470 }
471
472 private void removeOutEdges(List edges, Transition from) {
473 Iterator i = edges.iterator(); while (i.hasNext()) {
474 Edge e = (Edge)i.next();
475 Place to = e.getPlace();
476 _outedgestoremove.put(e.getPlace().getID(), from.getID(), getGraph().getOutEdge(from, to));
477 }
478 }
479
480
481
482 private void updateTransitionNode(Transition t) {
483 TransitionNode node = getTransitionNode(t);
484 _analyzer.updateTransitionNode(node);
485 ((org.glassbox.graphview.GGraphPane)getView()).repaintNode(node);
486 }
487
488 private void updatePlaceNode(Place p) {
489 PlaceNode node = getPlaceNode(p);
490 _analyzer.updatePlaceNode(node);
491 ((org.glassbox.graphview.GGraphPane)getView()).repaintNode(node);
492 }
493
494
495
496 private void updateReadEdge(Edge e, Transition to) {
497 Place from = e.getPlace();
498 ReadEdge arc = getGraph().getReadEdge(from, to);
499 _analyzer.updateReadEdge(arc);
500 ((org.glassbox.graphview.GGraphPane)getView()).repaintEdge(arc);
501 }
502
503 private void updateInEdge(Edge e, Transition to) {
504 Place from = e.getPlace();
505 InEdge arc = getGraph().getInEdge(from, to);
506 _analyzer.updateInEdge(arc);
507 ((org.glassbox.graphview.GGraphPane)getView()).repaintEdge(arc);
508 }
509
510 private void updateOutEdge(Edge e, Transition from) {
511 Place to = e.getPlace();
512 OutEdge arc = getGraph().getOutEdge(from, to);
513 _analyzer.updateOutEdge(arc);
514 ((org.glassbox.graphview.GGraphPane)getView()).repaintEdge(arc);
515 }
516
517
518
519
520
521 public void objectsAdded(IStructureObject parent, String namespace, String name, List objects) {
522 logger.debug("Objects added: {"+namespace+"}"+name);
523
524 IChildObject dummy = null;
525 if (isTransition(namespace, name)) {
526 addTransitionNodes(objects);
527 addEdges(objects);
528 } else if (isPlace(namespace, name)) {
529 addPlaceNodes(objects);
530 } else if (isReadEdge(namespace, name)) {
531 addReadEdges(objects, (ProtocolTransition)parent);
532 } else if (isInEdge(namespace, name)) {
533 addInEdges(objects, (ProtocolTransition)parent);
534 } else if (isOutEdge(namespace, name)) {
535 addOutEdges(objects, (ProtocolTransition)parent);
536 } else if ((dummy = isChildOfTransition(parent)) != null) {
537 updateTransitionNode((ProtocolTransition)dummy);
538 } else if ((dummy = isChildOfPlace(parent)) != null) {
539 updatePlaceNode((ProtocolPlace)dummy);
540 }
541 }
542
543 public void objectsRemoved(IStructureObject parent, String namespace, String name, List objects) {
544 logger.debug("Objects removed: {"+namespace+"}"+name);
545
546 IChildObject dummy = null;
547 if (isTransition(namespace, name)) {
548 removeTransitionNodes(objects);
549 removeEdges(objects);
550 } else if (isPlace(namespace, name)) {
551 removePlaceNodes(objects);
552 } else if (isReadEdge(namespace, name)) {
553 removeReadEdges(objects, (ProtocolTransition)parent);
554 } else if (isInEdge(namespace, name)) {
555 removeInEdges(objects, (ProtocolTransition)parent);
556 } else if (isOutEdge(namespace, name)) {
557 removeOutEdges(objects, (ProtocolTransition)parent);
558 } else if ((dummy = isChildOfTransition(parent)) != null) {
559 updateTransitionNode((ProtocolTransition)dummy);
560 } else if ((dummy = isChildOfPlace(parent)) != null) {
561 updatePlaceNode((ProtocolPlace)dummy);
562 }
563 }
564
565 public void propertyChanged(IStructureObject parent, String namespace, String name, Object newvalue) {
566 logger.debug("Property changed: {"+namespace+"}"+name);
567
568 IChildObject dummy = null;
569 if ((dummy = isChildOfReadEdge(parent)) != null) {
570 updateReadEdge((ProtocolEdge)dummy, (ProtocolTransition)dummy.getParent());
571 } else if ((dummy = isChildOfInEdge(parent)) != null) {
572 updateInEdge((ProtocolEdge)dummy, (ProtocolTransition)dummy.getParent());
573 } else if ((dummy = isChildOfOutEdge(parent)) != null) {
574 updateOutEdge((ProtocolEdge)dummy, (ProtocolTransition)dummy.getParent());
575 } else if ((dummy = isChildOfTransition(parent)) != null) {
576 updateTransitionNode((ProtocolTransition)dummy);
577 } else if ((dummy = isChildOfPlace(parent)) != null) {
578 updatePlaceNode((ProtocolPlace)dummy);
579 }
580 }
581
582 public void beginModifications(IRootObject structure) {
583 logger.debug("Got begin modifications.");
584
585 _edgestoadd.clear();
586 _nodestoadd.clear();
587 _edgestoremove.clear();
588 _nodestoremove.clear();
589 _pnodestoremove.clear();
590 _tnodestoremove.clear();
591 _readedgestoremove.clear();
592 _inedgestoremove.clear();
593 _outedgestoremove.clear();
594 }
595
596 public void endModifications(IRootObject structure) {
597 logger.debug("Got end modifications.");
598 logger.debug("Graph has "+getGraph().getNodes().size()+" nodes and "+getGraph().getEdges().size()+" edges.");
599
600 _nodestoremove.addAll(_pnodestoremove.values());
601 _nodestoremove.addAll(_tnodestoremove.values());
602
603 Iterator i = _readedgestoremove.values().iterator(); while (i.hasNext()) {
604 _edgestoremove.addAll(((Map)i.next()).values());
605 }
606 i = _inedgestoremove.values().iterator(); while (i.hasNext()) {
607 _edgestoremove.addAll(((Map)i.next()).values());
608 }
609
610 i = _outedgestoremove.values().iterator(); while (i.hasNext()) {
611 _edgestoremove.addAll(((Map)i.next()).values());
612 }
613
614 if (_nodestoadd.values().size() > 0 || _edgestoadd.size() > 0) {
615
616
617 Iterator nodes = getGraph().getNodes().iterator(); while (nodes.hasNext()) {
618 Node node = (Node)nodes.next();
619 node.setLocation(Integer.MIN_VALUE, Integer.MIN_VALUE);
620 }
621
622 Iterator edges = getGraph().getEdges().iterator(); while (edges.hasNext()) {
623 ArcEdge edge = (ArcEdge)edges.next();
624 edge.setControlPoints(null);
625 edge.setPointOfArrowAtStart(null);
626 edge.setPointOfArrowAtEnd(null);
627 edge.setLabelPosition(null);
628 }
629 }
630
631 logger.debug("Removing "+_nodestoremove.size()+" nodes and "+_edgestoremove.size()+" edges.");
632
633 getGraph().deleteElements(_nodestoremove, _edgestoremove);
634
635 logger.debug("Adding "+_nodestoadd.values().size()+" nodes and "+_edgestoadd.size()+" edges.");
636
637 getGraph().addElements(_nodestoadd.values(), _edgestoadd);
638 if (_nodestoadd.size() <= 1 && _edgestoadd.size() <= 1) {
639 if (!_nodestoadd.isEmpty())
640 getGraphPane().repaintNode((de.fzi.wim.guibase.graphview.graph.Node)_nodestoadd.values().iterator().next());
641 if (!_edgestoadd.isEmpty())
642 getGraphPane().repaintEdge((ArcEdge)_edgestoadd.get(0));
643 } else {
644 getGraphPane().repaint();
645 }
646 }
647
648 public void exception(IRootObject structure, Throwable x) {
649 logger.debug("Got exception.");
650
651 }
652
653
654
655
656
657 public JComponent getView() {
658 if (_graphpane == null) {
659 _graphpane = new GGraphPane(null);
660 _graphpane.addPropertyChangeListener(this);
661 }
662 return _graphpane;
663 }
664 }
665