1
2
3
4
5
6 package net.kwfgrid.gwui.graphviz;
7
8 import net.kwfgrid.gworkflowdl.structure.Edge;
9 import net.kwfgrid.gworkflowdl.structure.Place;
10 import net.kwfgrid.gworkflowdl.structure.Transition;
11 import net.kwfgrid.gworkflowdl.structure.Workflow;
12 import org.glassbox.dotparser.ASTgraph;
13 import org.glassbox.dotparser.DOTParser;
14 import org.glassbox.dotparser.ParseException;
15
16 import java.awt.*;
17 import java.io.StringReader;
18
19 /***
20 * This class can be used to apply a layout generated with graphviz to the properties of a workflow.
21 * <br>
22 * Graph properties:
23 * <ul>
24 * <li>gwui.layout.bounding-box.x</li>
25 * <li>gwui.layout.bounding-box.y</li>
26 * <li>gwui.layout.bounding-box.width</li>
27 * <li>gwui.layout.bounding-box.height</li>
28 * </ul>
29 * Node properties:
30 * <ul>
31 * <li>gwui.layout.x</li>
32 * <li>gwui.layout.y</li>
33 * </ul>
34 * Additional properties at transition node for each in- and outedge:
35 * <ul>
36 * <li>gwui.layout.inedge.<PLACEID>.cp (the control points of the spline)</li>
37 * <li>gwui.layout.inedge.<PLACEID>.ps (the start point of the head arrow, if present)</li>
38 * <li>gwui.layout.inedge.<PLACEID>.pe (the start point of the tail arrow, if present)</li>
39 * <li>gwui.layout.inedge.<PLACEID>.lp (the position of the edge's label, if present)</li>
40 * </ul>
41 */
42 public class DOTLayout2WorkflowProperties {
43 private String _dot;
44 private Workflow _target;
45
46 /***
47 * Constructor. The dot string should contain layout information for every node and edge in the workflow.
48 *
49 * @param dot The workflow in attributed dot format.
50 * @param target The workflow to set the properties.
51 */
52 public DOTLayout2WorkflowProperties(String dot, Workflow target) {
53 _dot = dot;
54 _target = target;
55 }
56
57 /***
58 * Execute the process. After calling this method the worklflow includes the layout information
59 * in the properties of the workflow, places and transitions.
60 *
61 * @throws GraphVizException If the layout information was incorrect.
62 */
63 public void run() throws GraphVizException {
64 try {
65
66 DOTParser parser = new DOTParser(new StringReader(_dot));
67 ASTgraph astgraph = parser.graph();
68 LayoutBuilder layoutbuilder = new LayoutBuilder();
69 ASTPreorderDirector layoutdirector = new ASTPreorderDirector(astgraph, layoutbuilder);
70 layoutdirector.build();
71
72
73 Rectangle bb = layoutbuilder.getGraphBoundingBox();
74 _target.getProperties().put("gwui.layout.bounding-box.x", "" + bb.x);
75 _target.getProperties().put("gwui.layout.bounding-box.y", "" + bb.y);
76 _target.getProperties().put("gwui.layout.bounding-box.width", "" + bb.width);
77 _target.getProperties().put("gwui.layout.bounding-box.height", "" + bb.height);
78
79 Place[] places = _target.getPlaces();
80
81 for (int i = 0; i < places.length; i++) {
82 Point pos = layoutbuilder.getNodePosition(places[i].getID());
83 if (pos == null)
84 throw new GraphVizException("No position for place " + places[i].getID());
85 places[i].getProperties().put("gwui.layout.x", "" + pos.x);
86 places[i].getProperties().put("gwui.layout.y", "" + (bb.height - pos.y));
87 }
88
89 Transition[] transitions = _target.getTransitions();
90
91 for (int i = 0; i < transitions.length; i++) {
92 Transition transition = transitions[i];
93
94 Point pos = layoutbuilder.getNodePosition(transition.getID());
95 if (pos == null)
96 throw new GraphVizException("No position for transition " + transition.getID());
97 transition.getProperties().put("gwui.layout.x", "" + pos.x);
98 transition.getProperties().put("gwui.layout.y", "" + (bb.height - pos.y));
99
100 Edge[] readedges = transition.getReadEdges();
101 for (int j = 0; j < readedges.length; j++) {
102 Edge edge = readedges[j];
103 String edgepropertyprefix = "gwui.layout.readedge." + edge.getPlaceID();
104 Point[] cp = layoutbuilder.getEdgeControlPoints(edge.getPlaceID(), transition.getID());
105 if (cp == null)
106 throw new GraphVizException("No control points for edge " + edge.getPlaceID() + " |-> " + transition.getID());
107 StringBuffer sb = new StringBuffer();
108 for (int k = 0; k < cp.length; k++) {
109 if (sb.length() > 0)
110 sb.append(",");
111 sb.append("(").append(cp[k].x).append(",").append(bb.height - cp[k].y).append(")");
112 }
113 transition.getProperties().put(edgepropertyprefix + ".cp", sb.toString());
114 if (layoutbuilder.hasEdgeArrowAtStart(edge.getPlaceID(), transition.getID())) {
115 Point ps = layoutbuilder.getEdgePointOfArrowAtStart(edge.getPlaceID(), transition.getID());
116 transition.getProperties().put(edgepropertyprefix + ".ps.x", "" + ps.x);
117 transition.getProperties().put(edgepropertyprefix + ".ps.y", "" + (bb.height - ps.y));
118 }
119 if (layoutbuilder.hasEdgeArrowAtEnd(edge.getPlaceID(), transition.getID())) {
120 Point pe = layoutbuilder.getEdgePointOfArrowAtEnd(edge.getPlaceID(), transition.getID());
121 transition.getProperties().put(edgepropertyprefix + ".pe.x", "" + pe.x);
122 transition.getProperties().put(edgepropertyprefix + ".pe.y", "" + (bb.height - pe.y));
123 }
124 Point lp = layoutbuilder.getEdgeLabelPosition(edge.getPlaceID(), transition.getID());
125 if (lp != null) {
126 transition.getProperties().put(edgepropertyprefix + ".lp.x", "" + lp.x);
127 transition.getProperties().put(edgepropertyprefix + ".lp.y", "" + (bb.height - lp.y));
128 }
129 }
130
131 Edge[] inedges = transition.getInEdges();
132 for (int j = 0; j < inedges.length; j++) {
133 Edge edge = inedges[j];
134 String edgepropertyprefix = "gwui.layout.inedge." + edge.getPlaceID();
135 Point[] cp = layoutbuilder.getEdgeControlPoints(edge.getPlaceID(), transition.getID());
136 if (cp == null)
137 throw new GraphVizException("No control points for edge " + edge.getPlaceID() + " -> " + transition.getID());
138 StringBuffer sb = new StringBuffer();
139 for (int k = 0; k < cp.length; k++) {
140 if (sb.length() > 0)
141 sb.append(",");
142 sb.append("(").append(cp[k].x).append(",").append(bb.height - cp[k].y).append(")");
143 }
144 transition.getProperties().put(edgepropertyprefix + ".cp", sb.toString());
145 if (layoutbuilder.hasEdgeArrowAtStart(edge.getPlaceID(), transition.getID())) {
146 Point ps = layoutbuilder.getEdgePointOfArrowAtStart(edge.getPlaceID(), transition.getID());
147 transition.getProperties().put(edgepropertyprefix + ".ps.x", "" + ps.x);
148 transition.getProperties().put(edgepropertyprefix + ".ps.y", "" + (bb.height - ps.y));
149 }
150 if (layoutbuilder.hasEdgeArrowAtEnd(edge.getPlaceID(), transition.getID())) {
151 Point pe = layoutbuilder.getEdgePointOfArrowAtEnd(edge.getPlaceID(), transition.getID());
152 transition.getProperties().put(edgepropertyprefix + ".pe.x", "" + pe.x);
153 transition.getProperties().put(edgepropertyprefix + ".pe.y", "" + (bb.height - pe.y));
154 }
155 Point lp = layoutbuilder.getEdgeLabelPosition(edge.getPlaceID(), transition.getID());
156 if (lp != null) {
157 transition.getProperties().put(edgepropertyprefix + ".lp.x", "" + lp.x);
158 transition.getProperties().put(edgepropertyprefix + ".lp.y", "" + (bb.height - lp.y));
159 }
160 }
161
162 Edge[] outedges = transition.getOutEdges();
163 for (int j = 0; j < outedges.length; j++) {
164 Edge edge = outedges[j];
165 String edgepropertyprefix = "gwui.layout.outedge." + edge.getPlaceID();
166 Point[] cp = layoutbuilder.getEdgeControlPoints(transition.getID(), edge.getPlaceID());
167 if (cp == null)
168 throw new GraphVizException("No control points for edge " + transition.getID() + " -> " + edge.getPlaceID());
169 StringBuffer sb = new StringBuffer();
170 for (int k = 0; k < cp.length; k++) {
171 if (sb.length() > 0)
172 sb.append(",");
173 sb.append("(").append(cp[k].x).append(",").append(bb.height - cp[k].y).append(")");
174 }
175 transition.getProperties().put(edgepropertyprefix + ".cp", sb.toString());
176 if (layoutbuilder.hasEdgeArrowAtStart(transition.getID(), edge.getPlaceID())) {
177 Point ps = layoutbuilder.getEdgePointOfArrowAtStart(transition.getID(), edge.getPlaceID());
178 transition.getProperties().put(edgepropertyprefix + ".ps.x", "" + ps.x);
179 transition.getProperties().put(edgepropertyprefix + ".ps.y", "" + (bb.height - ps.y));
180 }
181 if (layoutbuilder.hasEdgeArrowAtEnd(transition.getID(), edge.getPlaceID())) {
182 Point pe = layoutbuilder.getEdgePointOfArrowAtEnd(transition.getID(), edge.getPlaceID());
183 transition.getProperties().put(edgepropertyprefix + ".pe.x", "" + pe.x);
184 transition.getProperties().put(edgepropertyprefix + ".pe.y", "" + (bb.height - pe.y));
185 }
186 Point lp = layoutbuilder.getEdgeLabelPosition(transition.getID(), edge.getPlaceID());
187 if (lp != null) {
188 transition.getProperties().put(edgepropertyprefix + ".lp.x", "" + lp.x);
189 transition.getProperties().put(edgepropertyprefix + ".lp.y", "" + (bb.height - lp.y));
190 }
191 }
192 }
193 } catch (ParseException x) {
194 GraphVizException lx = new GraphVizException("Could not parse attributed dot.");
195 lx.initCause(x);
196 throw lx;
197 }
198 }
199 }