001: package com.opensymphony.workflow.designer;
002:
003: import java.util.*;
004: import java.util.List;
005: import java.awt.*;
006: import javax.swing.undo.UndoableEdit;
007:
008: import com.opensymphony.workflow.designer.event.JoinChangedEvent;
009: import com.opensymphony.workflow.designer.event.JoinChangedListener;
010: import com.opensymphony.workflow.loader.*;
011: import org.jgraph.graph.*;
012:
013: public class WorkflowGraphModel extends DefaultGraphModel {
014: private Collection stepCells = new HashSet();
015: private Collection splitCells = new HashSet();
016: private Collection joinCells = new HashSet();
017: private Collection initialActions = new ArrayList();
018: private ResultHolderList results = new ResultHolderList();
019: private IDGenerator resultIdGenerator = new IDGenerator();
020: private Layout layout;
021: private Object context = new Object();
022: private PaletteDescriptor palette;
023:
024: public WorkflowGraphModel(Layout layout) {
025: this .layout = layout;
026: }
027:
028: public Object getContext() {
029: return context;
030: }
031:
032: public PaletteDescriptor getPalette() {
033: return palette;
034: }
035:
036: public void setPalette(PaletteDescriptor palette) {
037: this .palette = palette;
038: }
039:
040: public JoinCell getJoinCell(int id) {
041: Iterator iter = joinCells.iterator();
042: while (iter.hasNext()) {
043: JoinCell cell = (JoinCell) iter.next();
044: if (cell.getJoinDescriptor().getId() == id) {
045: return cell;
046: }
047: }
048: return null;
049: }
050:
051: public StepCell getStepCell(int id) {
052: Iterator iter = stepCells.iterator();
053: while (iter.hasNext()) {
054: StepCell cell = (StepCell) iter.next();
055: if (cell.getDescriptor().getId() == id) {
056: return cell;
057: }
058: }
059: return null;
060: }
061:
062: public SplitCell getSplitCell(int id) {
063: Iterator iter = splitCells.iterator();
064: while (iter.hasNext()) {
065: SplitCell cell = (SplitCell) iter.next();
066: if (cell.getSplitDescriptor().getId() == id) {
067: return cell;
068: }
069: }
070: return null;
071: }
072:
073: public ResultEdge getResultCell(ResultDescriptor desc) {
074: // TODO
075: /*
076: Iterator iter = results.iterator();
077: while (iter.hasNext())
078: {
079: ResultHolder holder = (ResultHolder)iter.next();
080: if (holder.getDescriptor()==desc)
081: {
082: return holder.
083: }
084: }
085: */
086: if (desc == null)
087: return null;
088: WorkflowCell cell = null;
089: if (desc.getStep() != 0)
090: cell = getStepCell(desc.getStep());
091: else if (desc.getSplit() != 0)
092: cell = getSplitCell(desc.getSplit());
093: else if (desc.getJoin() != 0)
094: cell = getJoinCell(desc.getJoin());
095: else if (desc.getParent() instanceof ActionDescriptor) {
096: if (desc.getParent().getParent() == null) {
097: Iterator it = initialActions.iterator();
098: if (it.hasNext()) {
099: cell = (WorkflowCell) it.next();
100: }
101: }
102: }
103: if (cell != null) {
104: Object[] cells = new Object[] { cell };
105: Set edgeSet = WorkflowGraphModel.getEdges(this , cells);
106: Iterator edges = edgeSet.iterator();
107: while (edges.hasNext()) {
108: ResultEdge edge = (ResultEdge) edges.next();
109: if (edge.getDescriptor() == desc) {
110: return edge;
111: }
112: }
113: }
114: return null;
115: }
116:
117: public boolean acceptsTarget(Object edge, Object port) {
118: if (port == null)
119: return false;
120: WorkflowCell cell = (WorkflowCell) ((WorkflowPort) port)
121: .getParent();
122: if (cell instanceof InitialActionCell)
123: return false;
124: return true;
125: }
126:
127: public boolean acceptsSource(Object edge, Object port) {
128: if (port == null)
129: return false;
130: return true;
131: }
132:
133: public void processJoinChangeEvent(JoinCell cell) {
134: JoinDescriptor join = cell.getJoinDescriptor();
135:
136: List list = ((ConditionsDescriptor) join.getConditions().get(0))
137: .getConditions();
138: for (int i = 0; i < list.size(); i++) {
139: ConditionDescriptor cond = (ConditionDescriptor) list
140: .get(i);
141: if (cond.getType().equals("class")) {
142: String clazz = (String) cond.getArgs()
143: .get("class.name");
144: try {
145: Object obj = Class.forName(clazz).newInstance();
146: if (obj instanceof JoinChangedListener) {
147: JoinChangedEvent event = new JoinChangedEvent(
148: cell, this );
149: event.setArgs(cond.getArgs());
150: ((JoinChangedListener) obj).joinChanged(event);
151: cond.getArgs().putAll(event.getArgs());
152: }
153: } catch (ClassNotFoundException ex) {
154: System.out
155: .println("WARNING: Unable to find condition class "
156: + clazz);
157: } catch (Exception e) {
158: System.out
159: .println("WorkflowGraphModel.processJoinChangeEvent() Error loading condition "
160: + clazz);
161: e.printStackTrace();
162: }
163: }
164: }
165: }
166:
167: public void insertInitialActions(List initialActions,
168: InitialActionCell initialActionCell, Map attributes,
169: ParentMap pm, UndoableEdit[] edits) {
170: this .initialActions.add(initialActionCell);
171: // TODO:: currently only supports one action
172: for (int i = 0; i < initialActions.size() && i < 1; i++) {
173: // added by jackflit
174: if (i == 0) {
175: initialActionCell
176: .setActionDescriptor((ActionDescriptor) initialActions
177: .get(i));
178: }
179:
180: ActionDescriptor action = (ActionDescriptor) initialActions
181: .get(i);
182: Utils.checkId(context, action);
183: List conResults = action.getConditionalResults();
184: recordResults(initialActionCell, conResults, action);
185: ResultDescriptor result = action.getUnconditionalResult();
186: if (result != null) {
187: recordResult(initialActionCell, result, action);
188: }
189: Object[] cells = new Object[] { initialActionCell };
190: // Insert into Model
191: insert(cells, attributes, null, pm, edits);
192: }
193: }
194:
195: public void insertStepCell(StepCell stepCell, Map attributes,
196: ParentMap pm, UndoableEdit[] edits) {
197: stepCells.add(stepCell);
198: Utils.checkId(context, stepCell.getDescriptor());
199: Object[] cells = new Object[1 + stepCell.getChildCount()];
200: cells[0] = stepCell;
201: Object[] children = stepCell.getChildren().toArray();
202: System.arraycopy(children, 0, cells, 1, children.length);
203: // Insert into Model
204: insert(cells, attributes, null, pm, edits);
205: recordResults(stepCell);
206: }
207:
208: public void insertSplitCell(SplitCell splitCell, Map attributes,
209: ParentMap pm, UndoableEdit[] edits) {
210: splitCells.add(splitCell);
211: Utils.checkId(context, splitCell.getSplitDescriptor());
212: Object[] cells = new Object[] { splitCell };
213: // Insert into Model
214: insert(cells, attributes, null, pm, edits);
215: recordResults(splitCell);
216: }
217:
218: public void insertJoinCell(JoinCell joinCell, Map attributes,
219: ParentMap pm, UndoableEdit[] edits) {
220: joinCells.add(joinCell);
221: Utils.checkId(context, joinCell.getJoinDescriptor());
222: Object[] cells = new Object[] { joinCell };
223: // Insert into Model
224: insert(cells, attributes, null, pm, edits);
225: recordResults(joinCell);
226: }
227:
228: public void insertResultConnections() {
229: Iterator steps = stepCells.iterator();
230: while (steps.hasNext()) {
231: StepCell stepCell = (StepCell) steps.next();
232: processStepEndPointResult(stepCell);
233: }
234: Iterator splits = splitCells.iterator();
235: while (splits.hasNext()) {
236: SplitCell splitCell = (SplitCell) splits.next();
237: processSplitEndPointResult(splitCell);
238: }
239: Iterator joins = joinCells.iterator();
240: while (joins.hasNext()) {
241: JoinCell joinCell = (JoinCell) joins.next();
242: processJoinEndPointResult(joinCell);
243: this .processJoinChangeEvent(joinCell);
244: }
245: }
246:
247: public void recordResults(JoinCell fromCell) {
248: JoinDescriptor joinDescriptor = fromCell.getJoinDescriptor();
249: ResultDescriptor result = joinDescriptor.getResult();
250: if (result != null) {
251: recordResult(fromCell, result, null);
252: }
253: }
254:
255: public List getResultsToJoin(JoinCell joinCell) {
256: return results.getResultsToJoin(joinCell.getJoinDescriptor()
257: .getId());
258: }
259:
260: private void processJoinEndPointResult(JoinCell joinCell) {
261: int joinId = joinCell.getJoinDescriptor().getId();
262: Iterator results = this .results.getResultsToJoin(joinId)
263: .iterator();
264: while (results.hasNext()) {
265: ResultHolder result = (ResultHolder) results.next();
266: connectCells(result, joinCell);
267: }
268: }
269:
270: private void processSplitEndPointResult(SplitCell splitCell) {
271: int splitId = splitCell.getSplitDescriptor().getId();
272: Iterator results = this .results.getResultsToSplit(splitId)
273: .iterator();
274: while (results.hasNext()) {
275: ResultHolder result = (ResultHolder) results.next();
276: connectCells(result, splitCell);
277: }
278:
279: }
280:
281: public void recordResults(SplitCell fromCell) {
282: SplitDescriptor splitDescriptor = fromCell.getSplitDescriptor();
283: List results = splitDescriptor.getResults();
284: recordResults(fromCell, results, null);
285: }
286:
287: public List getResultsToStep(StepCell stepCell) {
288: return results.getResultsToStep(stepCell.getDescriptor()
289: .getId());
290: }
291:
292: /**
293: * Find Results that have StepCell's associated Step passed in as next Step. Connect all such cells
294: */
295: private void processStepEndPointResult(StepCell stepCell) {
296: int stepId = stepCell.getDescriptor().getId();
297: Iterator results = this .results.getResultsToStep(stepId)
298: .iterator();
299: while (results.hasNext()) {
300: ResultHolder result = (ResultHolder) results.next();
301: connectCells(result, stepCell);
302: }
303: }
304:
305: public void connectCells(WorkflowCell from,
306: ActionDescriptor action, WorkflowCell to,
307: ResultDescriptor result) {
308: WorkflowPort fromPort = (WorkflowPort) from.getChildAt(from
309: .getSelectedPort());
310: WorkflowPort toPort = (WorkflowPort) to.getChildAt(to
311: .getSelectedPort());
312:
313: resultIdGenerator.checkId(result.getId());
314: if (result.getId() == 0)
315: result.setId(resultIdGenerator.generateId());
316: // Create Edge
317: ResultEdge edge = new ResultEdge(result,
318: layout != null ? layout
319: .getLabelPosition(result.getId()) : null);
320:
321: // Connect Edge
322: ConnectionSet cs = new ConnectionSet(edge, fromPort, toPort);
323: Object[] cells = new Object[] { edge };
324: // Insert into Model
325: insert(cells, null, cs, null, null);
326: //toPort.assignIndex(edge);
327: //fromPort.assignIndex(edge);
328:
329: // process join changed event
330: if (to instanceof JoinCell) {
331: processJoinChangeEvent((JoinCell) to);
332: }
333: }
334:
335: /**
336: * Connects fromCell contained in resultCell to the toCell passed in.
337: */
338: private void connectCells(ResultHolder resultCell,
339: WorkflowCell toCell) {
340: WorkflowPort fromPort;
341: WorkflowPort toPort;
342:
343: // Create Edge
344: ResultDescriptor descriptor = resultCell.getDescriptor();
345: resultIdGenerator.checkId(descriptor.getId());
346: if (descriptor.getId() == 0)
347: descriptor.setId(resultIdGenerator.generateId());
348: ResultEdge edge;
349: if (layout != null) {
350: edge = new ResultEdge(descriptor, layout
351: .getLabelPosition(descriptor.getId()), layout
352: .getLineWidth(descriptor.getId()), new Color(layout
353: .getColor(descriptor.getId())), layout
354: .getRoutingPoints(descriptor.getId()));
355: fromPort = (WorkflowPort) resultCell.getFromCell()
356: .getChildAt(layout.getFromPort(descriptor.getId()));
357: toPort = (WorkflowPort) toCell.getChildAt(layout
358: .getToPort(descriptor.getId()));
359: } else {
360: edge = new ResultEdge(descriptor, null);
361: fromPort = (WorkflowPort) resultCell.getFromCell()
362: .getChildAt(
363: resultCell.getFromCell().getSelectedPort());
364: toPort = (WorkflowPort) toCell.getChildAt(toCell
365: .getSelectedPort());
366: }
367:
368: ConnectionSet cs = new ConnectionSet(edge, fromPort, toPort);
369: Object[] cells = new Object[] { edge };
370: // Insert into Model
371: insert(cells, null, cs, null, null);
372: //toPort.assignIndex(edge);
373: //fromPort.assignIndex(edge);
374: }
375:
376: /**
377: * When a Step is inserted, introspect it. find all the actions and add them to the GraphModel.
378: * Introspect each action and record results.
379: */
380: public void recordResults(StepCell fromCell) {
381: StepDescriptor stepDescriptor = fromCell.getDescriptor();
382: List actionList = stepDescriptor.getActions();
383: for (int i = 0; i < actionList.size(); i++) {
384: ActionDescriptor action = (ActionDescriptor) actionList
385: .get(i);
386: Utils.checkId(context, action);
387: List conResults = action.getConditionalResults();
388: recordResults(fromCell, conResults, action);
389: ResultDescriptor result = action.getUnconditionalResult();
390: if (result != null) {
391: recordResult(fromCell, result, action);
392: }
393:
394: }
395: }
396:
397: private void recordResults(WorkflowCell fromCell, List results,
398: ActionDescriptor action) {
399: for (int i = 0; i < results.size(); i++) {
400: ResultDescriptor result = (ResultDescriptor) results.get(i);
401: recordResult(fromCell, result, action);
402: }
403: }
404:
405: public ResultHolder recordResult(WorkflowCell fromCell,
406: ResultDescriptor result, ActionDescriptor action) {
407: Utils.checkId(context, result); // [KAP] This fixes the ID duplication bug
408: ResultHolder newCell = new ResultHolder(fromCell, result,
409: action);
410: results.add(newCell);
411: return newCell;
412: }
413:
414: public Collection getActivitiesList() {
415: List l = new ArrayList();
416: l.addAll(initialActions);
417: l.addAll(stepCells);
418: l.addAll(splitCells);
419: l.addAll(joinCells);
420: Iterator i = l.iterator();
421: Map edges = new HashMap();
422: while (i.hasNext()) {
423: WorkflowCell cell = (WorkflowCell) i.next();
424: //we know every edge has to start somewhere, so we don't need to check to cells
425: Iterator j = cell.getChildren().iterator();
426: while (j.hasNext()) {
427: Object port = j.next();
428: Iterator k = edges(port);
429: while (k.hasNext()) {
430: WorkflowEdge edge = (WorkflowEdge) k.next();
431: ResultDescriptor descriptor = (ResultDescriptor) edge
432: .getUserObject();
433: edges.put(new Integer(descriptor.getId()), edge);
434: }
435: }
436: }
437: l.addAll(edges.values());
438: return l;
439: }
440:
441: public boolean removeEdge(ResultEdge edge) {
442: ResultDescriptor result = edge.getDescriptor();
443:
444: ResultHolder cell = results.getResultCell(result);
445: DefaultGraphCell from = cell.getFromCell();
446: if (from instanceof ResultAware) {
447: // remove descriptor
448: ResultAware remove = (ResultAware) from;
449: if (!remove.removeResult(result)) {
450: return false;
451: }
452: Object[] objs = new Object[] { edge };
453: // remove edge
454: remove(objs);
455:
456: // remove result cell
457:
458: results.remove(cell);
459: // System.out.println(obj);
460: }
461:
462: if (result.getJoin() > 0) {
463: JoinCell join = getJoinCell(result.getJoin());
464: if (join != null) {
465: this .processJoinChangeEvent(join);
466: } else {
467: return false;
468: }
469: }
470:
471: return true;
472: }
473:
474: public boolean removeStep(StepCell cell) {
475: StepDescriptor step = cell.getDescriptor();
476:
477: // remove all edges and result cells
478: Set set = getEdges(this , new Object[] { cell });
479: Iterator iter = set.iterator();
480: while (iter.hasNext()) {
481: Object obj = iter.next();
482: if (obj instanceof ResultEdge) {
483: removeEdge((ResultEdge) obj);
484: }
485: }
486:
487: // remove step descriptor
488: WorkflowDescriptor workflow = (WorkflowDescriptor) step
489: .getParent();
490: List list = workflow.getSteps();
491: list.remove(step);
492:
493: // remove cell
494:
495: // 1. remove port
496: list = cell.getChildren();
497: for (int i = 0; i < list.size(); i++) {
498: remove(new Object[] { list.get(i) });
499: }
500: // 2. remove cell
501: remove(new Object[] { cell });
502:
503: // remove step cell from model
504: stepCells.remove(cell);
505:
506: return true;
507: }
508:
509: public boolean removeJoin(JoinCell cell) {
510: JoinDescriptor join = cell.getJoinDescriptor();
511:
512: // remove all edges and result cells
513: Set set = getEdges(this , new Object[] { cell });
514: Iterator iter = set.iterator();
515: while (iter.hasNext()) {
516: Object obj = iter.next();
517: if (obj instanceof ResultEdge) {
518: removeEdge((ResultEdge) obj);
519: }
520: }
521:
522: // remove join descriptor
523: WorkflowDescriptor workflow = (WorkflowDescriptor) join
524: .getParent();
525: List list = workflow.getJoins();
526: list.remove(join);
527:
528: // remove cell
529:
530: // 1. remove port
531: list = cell.getChildren();
532: for (int i = 0; i < list.size(); i++) {
533: remove(new Object[] { list.get(i) });
534: }
535: // 2. remove cell
536: remove(new Object[] { cell });
537:
538: // remove join cell from model
539: joinCells.remove(cell);
540:
541: return true;
542: }
543:
544: public boolean removeSplit(SplitCell cell) {
545:
546: SplitDescriptor split = cell.getSplitDescriptor();
547:
548: // remove all edges and result cells
549: Set set = getEdges(this , new Object[] { cell });
550: Iterator iter = set.iterator();
551: while (iter.hasNext()) {
552: Object obj = iter.next();
553: if (obj instanceof ResultEdge) {
554: removeEdge((ResultEdge) obj);
555: }
556: }
557:
558: // remove split descriptor
559: WorkflowDescriptor workflow = (WorkflowDescriptor) split
560: .getParent();
561: List list = workflow.getSplits();
562: list.remove(split);
563:
564: // remove cell
565:
566: // 1. remove port
567: list = cell.getChildren();
568: for (int i = 0; i < list.size(); i++) {
569: remove(new Object[] { list.get(i) });
570: }
571: // 2. remove cell
572: remove(new Object[] { cell });
573:
574: // remove split cell from model
575: splitCells.remove(cell);
576:
577: return true;
578: }
579: }
|