View Javadoc

1   /*
2    * Copyright (c) 2005, The K-Wf Grid Consortium
3    * Fraunhofer Institute for Computer Architecture and Software Technology
4    * See http://www.kwfgrid.eu and http://www.first.fraunhofer.de for more details.
5    */
6   package net.kwfgrid.gwui.graphview;
7   
8   import net.kwfgrid.gworkflowdl.structure.*;
9   import net.kwfgrid.gwui.graphviz.*;
10  import net.kwfgrid.gwui.graphview.*;
11  import net.kwfgrid.gwui.GWUI;
12  
13  import de.fzi.wim.guibase.graphview.layout.*;
14  import de.fzi.wim.guibase.graphview.graph.Node;
15  import de.fzi.wim.guibase.graphview.graph.Graph;
16  import de.fzi.wim.guibase.graphview.view.JGraphPane;
17  
18  import java.util.*;
19  
20  import org.apache.log4j.Logger;
21  
22  /***
23     A layout strategy which uses a remote graphviz instance to layout the graph.
24   */
25  public class DOTLayoutStrategy implements LayoutStrategy {
26      private static final Logger logger = Logger.getLogger(DOTLayoutStrategy.class);
27  
28      private static final int MAX_TIMER = 16;
29  
30      private WorkflowGraph _graph;
31      private boolean _valid;
32      private JGraphPane _view;
33      private HashMap _knownelements;
34      private String _knownworkflowid;
35      private int _timer;
36  
37      public DOTLayoutStrategy(JGraphPane view, WorkflowGraph graph) {
38  	logger.debug("Constructed new DOTLayoutStrategy for graph "+graph);
39  
40  	_timer = MAX_TIMER;
41  	_graph = graph;
42  	_view = view;
43  	_valid = false;
44  	_knownelements = new HashMap();
45  	_knownworkflowid = null;
46      }
47      
48      public boolean shouldExecuteStep() {
49  	return !_valid;
50      }
51  
52      public void executeGraphLayoutStep() {
53  	if (_timer == MAX_TIMER) {
54  	    Iterator nodes = _graph.getNodes().iterator(); while (nodes.hasNext()) {
55  		Node n = (Node)nodes.next();
56  		n.setLocation(-20000, -20000);
57  	    }
58  	    Iterator edges = _graph.getEdges().iterator(); while (edges.hasNext()) {
59  		ArcEdge e = (ArcEdge)edges.next();
60  		e.setControlPoints(null);
61  		e.setLabelPosition(null);
62  		e.setPointOfArrowAtStart(null);
63  		e.setPointOfArrowAtEnd(null);
64  	    }
65          _timer--;
66      } else if (_timer == 0) {
67  	    if (_graph.getEdges().size() > 0 && _graph.getNodes().size() > 0) {
68  		logger.debug("Executing graphviz layouter.");
69  		
70  		_knownworkflowid = new String(_graph.getWorkflow().getID());
71  		
72  		try {
73  		    GraphViz gviz = GWUI.getInstance().getGraphVizWS(_graph.getWorkflow().getID());
74  		    
75  		    // construct converter for gworkflowdl and create input dot
76  		    WorkflowGraph2DOTConverter builder = new WorkflowGraph2DOTConverter(_view);
77  		    ConversionDirector director = new ConversionDirector(_graph, builder, new ElementIterator(_graph));
78  		    director.build();
79  		    String dot = builder.getDOT();
80  		    
81  		    logger.debug("Input dot=\n"+dot);
82  		    
83  		    // run graphviz
84  		    String annotateddot = new String(gviz.dot("-Tdot", dot));
85  		    
86  		    logger.debug("Output dot=\n"+annotateddot);
87  		    
88  		    // apply layout to graph
89  		    (new DOTLayout2WorkflowGraph(annotateddot, _graph)).run();
90  		    
91  		    // remember layouted nodes.
92  		    _knownelements.clear();
93  		    Iterator i = _graph.getNodes().iterator(); while (i.hasNext()) {
94  			Node node = (Node)i.next();
95  			if (node instanceof PlaceNode) {
96  			    _knownelements.put(((PlaceNode)node).getPlace().getID(), node);
97  			} else if (node instanceof TransitionNode) {
98  			    _knownelements.put(((TransitionNode)node).getTransition().getID(), node);
99  			}
100 		    }
101 		    i = _graph.getEdges().iterator(); while (i.hasNext()) {
102 			ArcEdge edge = (ArcEdge)i.next();
103 			_knownelements.put(edgeID(edge), edge);
104 		    }
105 		    _valid = true;
106 		} catch (GraphVizException x) {
107 		    logger.error("Could not apply graphviz layout.", x);
108 		    _timer = MAX_TIMER;
109 		}
110 	    }
111 	} else {
112 	    _timer--;
113 	}
114     }
115 
116     private String edgeID(ArcEdge edge) {
117     if (edge instanceof ReadEdge) {
118         return edgeID(edge.getPlace(), edge.getTransition());
119     } else if (edge instanceof InEdge) {
120 	    return edgeID(edge.getPlace(), edge.getTransition());
121 	} else {
122 	    return edgeID(edge.getTransition(), edge.getPlace());
123 	}
124     }
125 
126     private String edgeID(PlaceNode from, TransitionNode to) {
127 	return from.getPlace().getID()+"->"+to.getTransition().getID();
128     }
129 
130     private String edgeID(TransitionNode from, PlaceNode to) {
131 	return from.getTransition().getID()+"->"+to.getPlace().getID();
132     }
133 
134     public Graph getGraph() {
135 	return _graph;
136     }
137 
138     public void elementsAdded(Collection nodes, Collection edges) {
139 	logger.debug("Elements added: "+(nodes!=null?nodes.size():0)+" Nodes and "+(edges!=null?edges.size():0)+" Edges.");
140 
141 	if (_valid) {
142 	    Workflow wf = _graph.getWorkflow();
143 	    
144 	    logger.debug("Workflow is "+wf);
145 	    
146 	    String ID = wf.getID();
147 	    
148 	    logger.debug("ID is "+ID+", known ID is "+_knownworkflowid+".");
149 	    
150 	    _valid = ID.equals(_knownworkflowid);
151 	    
152 	    logger.debug("After ID check layout is valid? "+_valid);
153 	    
154 	    if (nodes != null) {
155 		Iterator i = nodes.iterator(); while (i.hasNext()) {
156 		    Node node = (Node)i.next();
157 		    Node knownnode = null;
158 		    if (node instanceof PlaceNode) {
159 			knownnode = (Node)_knownelements.get(((PlaceNode)node).getPlace().getID());
160 		    } else if (node instanceof TransitionNode) {
161 			knownnode = (Node)_knownelements.get(((TransitionNode)node).getTransition().getID());
162 		    }	    
163 		    if (knownnode!=null) {
164 			node.setLocation(knownnode.getX(), knownnode.getY());
165 		    } else {
166 			_valid = false;
167 			node.setLocation(-20000, -20000);
168 		    }
169 		}
170 	    }
171 	    
172 	    logger.debug("After node check layout is valid? "+_valid);
173 	    
174 	    if (edges != null) {
175 		Iterator i = edges.iterator(); while (i.hasNext() && _valid) {
176 		    ArcEdge edge = (ArcEdge)i.next();
177 		    ArcEdge knownedge = (ArcEdge)_knownelements.get(edgeID(edge));
178 		    if (knownedge!=null) {
179 			edge.setControlPoints(knownedge.getControlPoints());
180 			edge.setLabelPosition(knownedge.getLabelPosition());
181 			edge.setPointOfArrowAtStart(knownedge.getPointOfArrowAtStart());
182 			edge.setPointOfArrowAtEnd(knownedge.getPointOfArrowAtEnd());
183 		    } else {
184 			_valid = false;			
185 		    }
186 		}
187 	    }
188 
189 	    logger.debug("After edge check layout is valid? "+_valid);
190 	}
191 
192 	if (!_valid) _timer = MAX_TIMER;
193     }
194 
195     public void elementsRemoved(Collection nodes, Collection edges) {
196 	// _valid = false;
197     }
198 
199     public void graphContentsChanged() {
200 	// _valid = false;
201     }
202 
203     public void notifyGraphLayoutUpdated() {
204 	// _valid = false;
205     }
206 }