001: /*
002: * argun 1.0
003: * Web 2.0 delivery framework
004: * Copyright (C) 2007 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.web.statemachine;
024:
025: import java.awt.geom.Point2D;
026: import java.awt.geom.Rectangle2D;
027: import java.util.ArrayList;
028: import java.util.Collection;
029: import java.util.Collections;
030: import java.util.Enumeration;
031: import java.util.Iterator;
032: import java.util.List;
033: import java.util.StringTokenizer;
034: import java.util.TreeSet;
035:
036: import org.jgraph.JGraph;
037: import org.jgraph.graph.CellView;
038: import org.jgraph.graph.EdgeView;
039: import org.jgraph.graph.GraphConstants;
040: import org.jgraph.graph.Port;
041:
042: import biz.hammurapi.sql.IDatabaseObject;
043: import biz.hammurapi.util.Attributable;
044: import biz.hammurapi.web.statemachine.sql.SmState;
045: import biz.hammurapi.web.statemachine.sql.SmStateImpl;
046: import biz.hammurapi.web.statemachine.sql.SmTransition;
047: import biz.hammurapi.web.statemachine.sql.SmTransitionImpl;
048: import biz.hammurapi.web.statemachine.sql.StateMachineImpl;
049: import biz.hammurapi.web.util.ComparablePoint;
050:
051: public class StateMachine {
052: private static final int X_TOLERANCE = 5;
053: private Collection states = new ArrayList();
054: private Collection transitions = new ArrayList();
055: private biz.hammurapi.web.statemachine.sql.StateMachine data;
056:
057: /**
058: * Creates new empty stateMachine
059: */
060: public StateMachine() {
061: data = new StateMachineImpl(true);
062: }
063:
064: /**
065: * Creates new empty stateMachine
066: */
067: public StateMachine(
068: biz.hammurapi.web.statemachine.sql.StateMachine data) {
069: this .data = data;
070: }
071:
072: /**
073: * @return State names
074: */
075: public boolean checkDuplicateStateName(String name) {
076: Iterator it = states.iterator();
077: while (it.hasNext()) {
078: if (((State) it.next()).getName().equals(name)) {
079: return true;
080: }
081: }
082: return false;
083: }
084:
085: /**
086: * @return State names
087: */
088: public State getState(String name) {
089: Iterator it = states.iterator();
090: while (it.hasNext()) {
091: State state = (State) it.next();
092: if (state.getName().equals(name)) {
093: return state;
094: }
095: }
096: return null;
097: }
098:
099: public Collection getStateNames() {
100: Collection ret = new TreeSet();
101: Iterator it = states.iterator();
102: while (it.hasNext()) {
103: State state = (State) it.next();
104: ret.add(state.getName());
105: }
106: return ret;
107: }
108:
109: private transient StateMachineApplet applet;
110:
111: public StateMachineApplet getApplet() {
112: return applet;
113: }
114:
115: public void setApplet(StateMachineApplet applet) {
116: this .applet = applet;
117: if (data != null) {
118: Collection statesData = (Collection) ((Attributable) data)
119: .getAttribute("states");
120: if (statesData != null) {
121: Iterator it = statesData.iterator();
122: while (it.hasNext()) {
123: SmState state = (SmState) it.next();
124: if (state.getGeometry() != null) {
125: int idx = state.getGeometry().indexOf(',');
126: double x = java.lang.Double.parseDouble(state
127: .getGeometry().substring(0, idx));
128: double y = java.lang.Double.parseDouble(state
129: .getGeometry().substring(idx + 1));
130: Point2D point = new Point2D.Double(x, y);
131: State theState = new State(this , state);
132: states.add(theState);
133: applet.insert(point, theState);
134: }
135: }
136: }
137:
138: Collection transitionsData = (Collection) ((Attributable) data)
139: .getAttribute("transitions");
140: if (transitionsData != null) {
141: Iterator it = transitionsData.iterator();
142: while (it.hasNext()) {
143: SmTransition transition = (SmTransition) it.next();
144: if (transition.getGeometry() != null) {
145: StringTokenizer st = new StringTokenizer(
146: transition.getGeometry(), ";");
147: List points = new ArrayList();
148: while (st.hasMoreTokens()) {
149: String token = st.nextToken();
150: int idx = token.indexOf(',');
151: double x = java.lang.Double
152: .parseDouble(token
153: .substring(0, idx));
154: double y = java.lang.Double
155: .parseDouble(token
156: .substring(idx + 1));
157: Point2D point = new Point2D.Double(x, y);
158: points.add(point);
159: }
160: Transition theTransition = new Transition(this ,
161: transition);
162: transitions.add(theTransition);
163: Port sourcePort = null;
164: SmState transitionSource = (SmState) ((IDatabaseObject) transition)
165: .getColumnAttribute("FROM_TASK",
166: "state");
167: Iterator sit = states.iterator();
168: while (sit.hasNext()) {
169: State candidate = (State) sit.next();
170: if (candidate.getData() == transitionSource) {
171: Enumeration children = candidate
172: .children();
173: children.nextElement();
174: sourcePort = (Port) children
175: .nextElement();
176: break;
177: }
178: }
179:
180: Port targetPort = null;
181: SmState transitionTarget = (SmState) ((IDatabaseObject) transition)
182: .getColumnAttribute("TO_TASK", "state");
183: sit = states.iterator();
184: while (sit.hasNext()) {
185: State candidate = (State) sit.next();
186: if (candidate.getData() == transitionTarget) {
187: Enumeration children = candidate
188: .children();
189: targetPort = (Port) children
190: .nextElement();
191: break;
192: }
193: }
194:
195: if (sourcePort == null || targetPort == null) {
196: throw new IllegalStateException(
197: "Transition source or target not found");
198: }
199:
200: applet.connect(theTransition, sourcePort,
201: targetPort, points);
202: }
203: }
204: }
205: }
206: }
207:
208: public State createState() {
209: String stateName = "State 1";
210: for (int i = 1; checkDuplicateStateName(stateName); ++i) {
211: stateName = "State " + i;
212: }
213:
214: SmState data = new SmStateImpl(true);
215: data.setName(stateName);
216: State ret = new State(this , data);
217: states.add(ret);
218: return ret;
219: }
220:
221: public Transition createTransition() {
222: Transition ret = new Transition(this ,
223: new SmTransitionImpl(true));
224: transitions.add(ret);
225: return ret;
226: }
227:
228: public void removeTransition(Transition transition) {
229: transition.invalidate();
230: }
231:
232: public void removeState(State state) {
233: state.invalidate();
234: }
235:
236: /**
237: * Stores geometry in stateMachine elements
238: * @param graph
239: */
240: public void storeGeometry() {
241: JGraph graph = getApplet().getGraph();
242: List comparablePoints = new ArrayList();
243: Iterator it = states.iterator();
244: while (it.hasNext()) {
245: State state = (State) it.next();
246: if (state.isValid()) {
247: CellView stateView = graph.getGraphLayoutCache()
248: .getMapping(state, false);
249: Rectangle2D bounds = stateView.getBounds();
250: double x = bounds.getX();
251: double y = bounds.getY();
252: state.getData().setGeometry(x + "," + y);
253: comparablePoints.add(new ComparablePoint(x, y, state,
254: X_TOLERANCE, true));
255: } else {
256: it.remove();
257: }
258: }
259:
260: Collections.sort(comparablePoints);
261: it = comparablePoints.iterator();
262: for (int i = 0; it.hasNext(); ++i) {
263: ((State) ((ComparablePoint) it.next()).getUserObject())
264: .getData().setStateOrder(i);
265: }
266:
267: comparablePoints.clear();
268: it = transitions.iterator();
269: while (it.hasNext()) {
270: Transition transition = (Transition) it.next();
271: if (transition.isValid()) {
272: EdgeView stateView = (EdgeView) graph
273: .getGraphLayoutCache().getMapping(transition,
274: false);
275: List points = stateView.getPoints();
276: if (points == null) {
277: transition.getData().setGeometry("");
278: } else {
279: StringBuffer geometryBuffer = new StringBuffer();
280: Iterator pit = points.iterator();
281: for (int i = 0; pit.hasNext(); ++i) {
282: Object point = pit.next();
283: if ((point instanceof Point2D)) {
284: Point2D thePoint = (Point2D) point;
285: geometryBuffer.append(thePoint.getX() + ","
286: + thePoint.getY() + ";");
287: }
288:
289: if (i == 1) {
290: if ((point instanceof Point2D)) {
291: Point2D thePoint = (Point2D) point;
292: ComparablePoint cp = new ComparablePoint(
293: thePoint, transition,
294: X_TOLERANCE, true);
295: comparablePoints.add(cp);
296: } else if (point instanceof Port) {
297: Rectangle2D bounds = GraphConstants
298: .getBounds(((Port) point)
299: .getAttributes());
300: ComparablePoint cp = new ComparablePoint(
301: bounds.getCenterX(), bounds
302: .getCenterY(),
303: transition, X_TOLERANCE, true);
304: comparablePoints.add(cp);
305: }
306: }
307: }
308: transition.getData().setGeometry(
309: geometryBuffer.toString());
310: }
311: } else {
312: it.remove();
313: }
314: }
315:
316: Collections.sort(comparablePoints);
317: it = comparablePoints.iterator();
318: for (int i = 0; it.hasNext(); ++i) {
319: ((Transition) ((ComparablePoint) it.next()).getUserObject())
320: .getData().setTransitionOrder(i);
321: }
322: }
323:
324: public String getDescription() {
325: return data.getDescription();
326: }
327:
328: public String getName() {
329: return data.getName();
330: }
331:
332: public void setDescription(String description) {
333: data.setDescription(description);
334: }
335:
336: public void setName(String name) {
337: data.setName(name);
338: }
339:
340: public biz.hammurapi.web.statemachine.sql.StateMachine getData() {
341: ArrayList statesData = new ArrayList();
342: Iterator it = states.iterator();
343: while (it.hasNext()) {
344: State state = (State) it.next();
345: if (state.isValid()) {
346: statesData.add(state.getData());
347: }
348: }
349: ((Attributable) data).setAttribute("states", statesData);
350:
351: ArrayList transitionsData = new ArrayList();
352: it = transitions.iterator();
353: while (it.hasNext()) {
354: Transition transition = (Transition) it.next();
355: if (transition.isValid()) {
356: Object sourceData = transition.getSourceState()
357: .getData();
358: ((IDatabaseObject) transition.getData())
359: .setColumnAttribute("FROM_STATE", "state",
360: sourceData);
361:
362: Object targetData = transition.getTargetState()
363: .getData();
364: ((IDatabaseObject) transition.getData())
365: .setColumnAttribute("TO_STATE", "state",
366: targetData);
367:
368: transitionsData.add(transition.getData());
369: }
370: }
371: ((Attributable) data).setAttribute("transitions",
372: transitionsData);
373:
374: return data;
375: }
376:
377: public String getInitialState() {
378: return data.getInitialState();
379: }
380:
381: public void setInitialState(String arg0) {
382: data.setInitialState(arg0);
383: }
384:
385: }
|