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.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              // extract layout information from dot
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              // apply the layout information to the workflow
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 }