Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: domain/TransMgr.java


1   /*
2    * Danet GmbH
3    * Beratung und Software-Entwicklung
4    * Geschäftstelle AN
5    *
6    * $Id: TransMgr.java,v 1.41 2003/09/19 13:12:29 lipp Exp $
7    *
8    * $Log: TransMgr.java,v $
9    * Revision 1.41  2003/09/19 13:12:29  lipp
10   * Adapted to closed.completed having a substate.
11   *
12   * Revision 1.40  2003/05/31 20:05:25  lipp
13   * Added support for different condition types.
14   *
15   * Revision 1.39  2003/04/26 16:12:35  lipp
16   * Moved some classes to reduce package dependencies.
17   *
18   * Revision 1.38  2003/04/24 20:51:21  lipp
19   * Fixed some warnings.
20   *
21   * Revision 1.37  2003/02/03 10:09:27  lipp
22   * Adapted to latest changes in src.
23   *
24   * Revision 1.36  2002/11/25 21:16:23  lipp
25   * Adapted to transition interface changes.
26   *
27   * Revision 1.35  2002/11/19 15:14:52  lipp
28   * New transition manager.
29   *
30   * Revision 1.34  2002/11/15 15:13:54  lipp
31   * Clarified usage of transitions as attribute. Included in caching.
32   *
33   * Revision 1.33  2002/11/11 12:20:45  lipp
34   * Some fixes.
35   *
36   * Revision 1.32  2002/11/04 08:40:25  barzik
37   * adapted to several modifications in the workflow component
38   *
39   * Revision 1.31  2002/10/21 19:08:05  lipp
40   * Continuing implementation of new state handling.
41   *
42   * Revision 1.30  2002/10/09 15:17:51  lipp
43   * Improved start mode handling.
44   *
45   * Revision 1.29  2002/10/09 14:27:33  lipp
46   * Intermediate, compilable state.
47   *
48   * Revision 1.28  2002/09/11 14:17:22  lipp
49   * Execptions using msgs now.
50   *
51   * Revision 1.27  2002/09/08 18:46:39  lipp
52   * Clean up.
53   *
54   * Revision 1.26  2002/08/30 13:37:05  lipp
55   * Using Workflow engine facade now.
56   *
57   * Revision 1.25  2002/08/30 09:06:40  lipp
58   * Renamed internal state to typed state and use polymorphism for type
59   * names where possible.
60   *
61   * Revision 1.24  2002/08/28 12:58:03  lipp
62   * Fixed unittests.
63   *
64   * Revision 1.23  2002/08/28 12:47:20  lipp
65   * Starting new process generation.
66   *
67   * Revision 1.22  2002/08/22 15:19:34  lipp
68   * Redesign of EJB persistence.
69   *
70   * Revision 1.21  2002/08/21 22:06:48  lipp
71   * Finished transition to ProcessMgrStub.
72   *
73   * Revision 1.20  2002/08/02 09:28:53  huaiyang
74   * Use JDOM.
75   *
76   * Revision 1.19  2002/06/27 10:47:35  lipp
77   * Adapted to change in return type.
78   *
79   * Revision 1.18  2002/05/27 14:55:29  lipp
80   * Adapted to API changes.
81   *
82   * Revision 1.17  2002/02/04 22:43:12  lipp
83   * Adapted tests to changed.
84   *
85   * Revision 1.16  2002/02/04 15:18:55  lipp
86   * Made ActivityFinderAndKey visible in EJB Remote interface.
87   *
88   * Revision 1.15  2002/02/03 21:41:41  lipp
89   * Cleaned up unittests.
90   *
91   * Revision 1.14  2002/01/23 15:42:04  lipp
92   * Adapted to interface changes.
93   *
94   * Revision 1.13  2001/12/20 09:39:03  lipp
95   * Adapted to modified method signature.
96   *
97   * Revision 1.12  2001/12/18 22:16:53  lipp
98   * Restructured DOM generation, implemented "assignments" method from ras.
99   *
100  * Revision 1.11  2001/12/15 12:47:07  lipp
101  * Getting an ActivityFinder implemented.
102  *
103  * Revision 1.10  2001/12/13 21:00:05  lipp
104  * Simplified temporary implementation of a requester.
105  *
106  * Revision 1.9  2001/12/13 09:41:04  lipp
107  * equals and hashCode methods added.
108  *
109  * Revision 1.8  2001/10/25 17:15:51  lipp
110  * Renamed getTransitionsRefs() to getNextActivities() (more appropriate
111  * name) and added TransitionRefs to DOM representatiosn.
112  *
113  * Revision 1.7  2001/10/23 14:07:15  lipp
114  * Adapted to interface changes.
115  *
116  * Revision 1.6  2001/10/09 11:55:07  montag
117  * TransitionManager now without ejbs.
118  * transitionref list now contains Activity elements.
119  *
120  * Revision 1.5  2001/10/09 07:43:51  montag
121  * BaseElement reactivated
122  *
123  * Revision 1.4  2001/10/08 10:58:24  lipp
124  * Adapted to interface/implementation separation in domain.
125  *
126  * Revision 1.3  2001/10/04 08:01:54  montag
127  * unittests adopt for new transitionmanager
128  *
129  * Revision 1.2  2001/09/27 07:26:08  montag
130  * Default behavior for activities is now
131  * AND-Join and AND-Split.
132  * TO DO: XOR-Join and XOR-Split
133  *
134  * Revision 1.1  2001/09/26 08:15:39  montag
135  * allToActivities() implemented.
136  * test case for transition manager.
137  *
138  *
139  */
140 package domain;
141 
142 import java.util.ArrayList;
143 import java.util.Collection;
144 import java.util.Iterator;
145 import java.util.List;
146 import java.util.Vector;
147 
148 import java.rmi.RemoteException;
149 
150 import de.danet.an.workflow.omgcore.AlreadyRunningException;
151 import de.danet.an.workflow.omgcore.CannotStartException;
152 import de.danet.an.workflow.omgcore.InvalidDataException;
153 import de.danet.an.workflow.omgcore.InvalidStateException;
154 import de.danet.an.workflow.omgcore.ProcessData;
155 import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
156 import de.danet.an.workflow.omgcore.UpdateNotAllowedException;
157 import de.danet.an.workflow.omgcore.WfActivity;
158 
159 import de.danet.an.workflow.api.Activity;
160 import de.danet.an.workflow.api.Transition;
161 
162 import de.danet.an.workflow.domain.TransitionDefinition;
163 
164 import de.danet.an.workflow.engine.TransitionManager;
165 
166 import junit.framework.Test;
167 import junit.framework.TestCase;
168 import junit.framework.TestSuite;
169 
170 /**
171  * Zusammenstellung aller TransitionMgrTests.
172  * @author <a href="mailto:lipp@danet.de"></a>
173  * @version 1.0
174  */
175 public class TransMgr extends TestCase {
176 
177     /**
178      * Konstruktor zum Erzeugen eines TestCase
179      * @param name a <code>String</code> value
180      */
181     public TransMgr(String name) {
182   super (name);
183     }
184 
185     /**
186      * Stellt diese TestSuite zusammen.
187      * @return a <code>Test</code> value
188      */
189     public static Test suite() {
190         TestSuite suite = new TestSuite();
191   // Because the transition manager currently
192   // works only on EJB, the tests are deactivated
193   // until there are new interfaces for process and
194   // activity to e.g. retrieve the transition ref list
195   // from a process.
196   suite.addTest(new TransMgr("transTest1"));
197          suite.addTest(new TransMgr("joinAndSplit1"));
198         return suite;
199     }
200   
201     /**
202      * Test for Process with activities and transitions
203      * @exception Exception if an error occurs
204      */
205     public void transTest1() throws Exception {
206   TestProcess p = getProcess();
207   assertTrue (p != null);
208   Activity a1 = getActivity(p,1);
209   assertTrue (a1 != null);
210   Activity a2 = getActivity(p,2);
211   assertTrue (a2 != null);
212   Collection c = new Vector();
213   c.add(a1);
214   c.add(a2);
215   p.setActivities(c);
216   String group = "t";
217   int order = 0;
218   p.createTransition("t",group, order, a1,a2);
219   p.testTransitionManager();
220     }
221 
222     /**
223      * Test for Process with activities and transitions
224      * @exception Exception if an error occurs
225      */
226     public void joinAndSplit1() throws Exception {
227   TestProcess p = getProcess();
228   assertTrue (p != null);
229   TestActivity a[] = new TestActivity[9];
230   Collection c = new Vector();
231   for (int i = 0; i <9; i++) {
232       a[i] = (TestActivity)getActivity(p,i);
233       a[i].setJoinAndSplitMode("AND", "AND");
234       c.add(a[i]);
235   }
236   p.setActivities(c);
237   List tr = new ArrayList();
238   TransitionDefinition t[] = new TransitionDefinition[12];
239   t[0]= new TransitionDefinition
240       (p.key(),"0","0",0,a[0],a[1],Transition.COND_TYPE_CONDITION,null);
241   t[1]= new TransitionDefinition
242       (p.key(),"1","1",0,a[0],a[2],Transition.COND_TYPE_CONDITION,null);
243   t[2]= new TransitionDefinition
244       (p.key(),"2","2",0,a[1],a[3],Transition.COND_TYPE_CONDITION,null);
245   t[3]= new TransitionDefinition
246       (p.key(),"3","3",0,a[1],a[4],Transition.COND_TYPE_CONDITION,null);
247   t[4]= new TransitionDefinition
248       (p.key(),"4","4",0,a[2],a[4],Transition.COND_TYPE_CONDITION,null);
249   t[5]= new TransitionDefinition
250       (p.key(),"5","5",0,a[2],a[5],Transition.COND_TYPE_CONDITION,null);
251   t[6]= new TransitionDefinition
252       (p.key(),"6","6",0,a[3],a[6],Transition.COND_TYPE_CONDITION,null);
253   t[7]= new TransitionDefinition
254       (p.key(),"7","7",0,a[4],a[6],Transition.COND_TYPE_CONDITION,null);
255   t[8]= new TransitionDefinition
256       (p.key(),"8","8",0,a[4],a[7],Transition.COND_TYPE_CONDITION,null);
257   t[9]= new TransitionDefinition
258       (p.key(),"9","9",0,a[5],a[7],Transition.COND_TYPE_CONDITION,null);
259   t[10]= new TransitionDefinition
260       (p.key(),"10","10",0,a[6],a[8],Transition.COND_TYPE_CONDITION,null);
261   t[11]= new TransitionDefinition
262       (p.key(),"11","11",0,a[7],a[8],Transition.COND_TYPE_CONDITION,null);
263   for (int i = 0; i <12; i++) {
264       p.createTransition (t[i].id(), t[i].group(), t[i].order(), 
265         t[i].from(), t[i].to());
266   }
267   p.start();
268 
269   for (int i = 0; i < 9; i++) {
270       assertTrue(a[i].state().startsWith("closed.completed"));
271   } 
272 
273     }
274 
275     //////////////////////////////////////////////////////////
276 
277     private TestProcess getProcess() {
278   return new TestProcess("p1");
279     }
280     
281     /**
282      * Describe class <code>TestProcess</code> here.
283      *
284      */
285     public class TestProcess extends VolatileProcess {
286 
287   /**
288    * Creates a new <code>TestProcess</code> instance.
289    *
290    * @param key a <code>String</code> value
291    */
292   public TestProcess (String key) {
293       super (key);
294   }
295 
296   /**
297    * Test the TransitionManager.<p>
298    * Preconditions:
299    * <ul>
300    * <li>The process has not been started.</li>
301    * <li>There a two activities an one transition
302    * between these two activities.</li>
303    * </ul>
304    * @exception Exception if an error occurs
305    */
306   public void testTransitionManager() throws Exception {
307       assertTrue(transitions().size() > 0);
308       TransitionManager tm = transitionManager();
309       assertTrue(tm != null);
310       Collection a = steps();
311       // Test allOpenableActivities()
312       Collection c = tm.startableActivities();
313       // only the first activity should be openable
314       assertTrue(c.size() == 1);
315   }
316       
317   /**
318    * Describe <code>start</code> method here.
319    *
320    * @exception RemoteException if an error occurs
321    * @exception CannotStartException if an error occurs
322    * @exception AlreadyRunningException if an error occurs
323    */
324   public void start () throws RemoteException,
325       CannotStartException, AlreadyRunningException {
326       // set process state
327       super.start();
328       
329       // start all activities
330       TransitionManager tm = transitionManager();
331       Collection activitiesToStart = tm.startableActivities();
332       Iterator it = activitiesToStart.iterator();
333       while (it.hasNext()) {
334     WfActivity a = (WfActivity)it.next();
335     try {
336         // Due to concurrency, an activity 
337         // could be started interim.
338         if (!a.workflowState()
339       .equals(State.CLOSED) 
340       && a.state()
341       .equals("open.not_running.not_runnable")) {
342       a.setProcessContext(null);
343         }    
344     } catch (InvalidDataException ide) {
345         throw new CannotStartException("");
346     } catch (UpdateNotAllowedException ue) {
347         throw new CannotStartException("");
348     }      
349       }
350   }
351 
352   /**
353    * This method notifies the process that one of its 
354    * activities has changed its state. For the 1. iteration
355    * an activity signals that it has been completed.
356    * The next activity (if exists) are searched and started.
357    * @param i a <code>Long</code> value
358    * @param s the actual state of the activity
359    */
360   public void complete (Long i, State s)  {
361       try {
362     // checkAllActivities
363     if (transitionManager().isAtEnd()) {
364         // TODO: remove condition check
365         if (!State.fromString(state())
366       .isSameOrSubState(ClosedState.ABORTED)) {
367       // last activity executed, finish process
368       updateState(ClosedState.COMPLETED);
369         }
370     } else {
371         // start all runnableActivities
372         Collection activitiesToStart = transitionManager()
373       .startableActivities();
374         Iterator it = activitiesToStart.iterator();
375         while (it.hasNext()) {
376       WfActivity a = (WfActivity)it.next();
377       try {
378           // Due to concurrency, an activity 
379           // could be started interim.
380           if (!a.workflowState()
381         .equals(State.CLOSED) 
382         && a.state()
383         .equals("open.not_running.not_runnable")) {
384         a.setProcessContext(null);
385           }
386       } catch (UpdateNotAllowedException ue) {
387           ue.printStackTrace();
388       }
389         }
390     }
391       } catch (RemoteException re) {
392     re.printStackTrace();
393       } catch (InvalidStateException re) {
394     re.printStackTrace();
395       } catch (InvalidDataException re) {
396     re.printStackTrace();
397       }
398   }
399     }
400 
401     private Activity getActivity(TestProcess p, int i) {
402   return new TestActivity(p,i);
403     }
404 
405     /**
406      * Describe class <code>TestActivity</code> here.
407      *
408      */
409     public class TestActivity extends VolatileActivity {
410 
411   private int id;
412 
413   /**
414    * Describe <code>thisRemote</code> method here.
415    *
416    * @return an <code>Activity</code> value
417    */
418   protected Activity thisRemote () {
419       return this;
420   }
421   /**
422    * Describe <code>setJoinAndSplitMode</code> method here.
423    *
424    * @param join a <code>String</code> value
425    * @param split a <code>String</code> value
426    */
427   public void setJoinAndSplitMode(String join, String split) {
428       setInternalJoinMode(join);
429       setInternalSplitMode(split);
430   }
431   /**
432    * Creates a new <code>TestActivity</code> instance.
433    *
434    * @param p a <code>TestProcess</code> value
435    * @param i an <code>int</code> value
436    */
437   public TestActivity(TestProcess p, int i) {
438       super (p, "ta" + i);
439       id = i;
440       setPaName ("ta" + i);
441       setPaDescription ("ta" + i);
442   }
443   /**
444    * Describe <code>setProcessContext</code> method here.
445    *
446    * @param newValue a <code>ProcessData</code> value
447    * @exception InvalidDataException if an error occurs
448    * @exception UpdateNotAllowedException if an error occurs
449    * @exception RemoteException if an error occurs
450    */
451   public void setProcessContext (ProcessData newValue) 
452       throws InvalidDataException, UpdateNotAllowedException,
453        RemoteException {
454       
455       try {
456     updateState (OpenState.NOT_RUNNING);
457     
458     if (startMode() == StartFinishMode.MANUAL) {
459         // hold state
460     } else {
461         if (finishMode() == StartFinishMode.MANUAL) {
462       changeState("open.running");
463         } else {
464       changeState("open.running");
465       updateState (ClosedState.COMPLETED);
466         }
467     }
468       } catch (InvalidStateException ie) {
469     throw new UpdateNotAllowedException(ie.getMessage());
470       } catch (TransitionNotAllowedException te) {
471     throw new UpdateNotAllowedException(te.getMessage());
472       }  
473   }
474 
475   /**
476    * Describe <code>pubSetState</code> method here.
477    *
478    * @param s a <code>State</code> value
479    * @exception InvalidStateException if an error occurs
480    */
481   public void pubSetState (State s) 
482       throws InvalidStateException {
483       updateState (s);
484   }
485 
486     }
487 }
488