KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jbpm > graph > exe > ProcessInstance


1 package org.jbpm.graph.exe;
2
3 import java.io.Serializable JavaDoc;
4 import java.util.ArrayList JavaDoc;
5 import java.util.Date JavaDoc;
6 import java.util.HashMap JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.List JavaDoc;
9 import java.util.Map JavaDoc;
10
11 import org.jbpm.context.exe.ContextInstance;
12 import org.jbpm.db.JbpmSession;
13 import org.jbpm.graph.def.Event;
14 import org.jbpm.graph.def.ProcessDefinition;
15 import org.jbpm.graph.def.Transition;
16 import org.jbpm.graph.log.ProcessInstanceCreateLog;
17 import org.jbpm.graph.log.ProcessInstanceEndLog;
18 import org.jbpm.graph.node.ProcessState;
19 import org.jbpm.logging.exe.LoggingInstance;
20 import org.jbpm.module.def.ModuleDefinition;
21 import org.jbpm.module.exe.ModuleInstance;
22 import org.jbpm.scheduler.exe.SchedulerInstance;
23 import org.jbpm.taskmgmt.exe.TaskMgmtInstance;
24
25
26 /**
27  * is one execution of a {@link org.jbpm.graph.def.ProcessDefinition}.
28  * To create a new process execution of a process definition, just use the
29  * {@link #ProcessInstance(ProcessDefinition)}.
30  *
31  */

32 public class ProcessInstance implements Serializable JavaDoc {
33
34   private static final long serialVersionUID = 1L;
35   
36   long id = 0;
37   protected Date JavaDoc start = null;
38   protected Date JavaDoc end = null;
39   protected ProcessDefinition processDefinition = null;
40   protected Token rootToken = null;
41   protected Token superProcessToken = null;
42   protected Map JavaDoc instances = null;
43   protected Map JavaDoc transientInstances = null;
44   protected List JavaDoc runtimeActions = null;
45
46   // constructors /////////////////////////////////////////////////////////////
47

48   public ProcessInstance() {
49   }
50
51   /**
52    * creates a new process instance for the given process definition and
53    * puts the root-token (=main path of execution) in the start state.
54    * For each of the optional module definitions contained in the
55    * {@link ProcessDefinition}, the corresponding module instance
56    * will be created.
57    * @throws NullPointerException if processDefinition is null.
58    */

59   public ProcessInstance( ProcessDefinition processDefinition ) {
60     if (processDefinition==null) throw new NullPointerException JavaDoc("can't create a process instance when processDefinition is null");
61     
62     // initialize the members
63
this.processDefinition = processDefinition;
64     this.rootToken = new Token(this);
65     this.start = new Date JavaDoc();
66
67     // create the optional definitions
68
Map JavaDoc definitions = processDefinition.getDefinitions();
69     // if the state-definition has optional definitions
70
if ( definitions != null ) {
71       instances = new HashMap JavaDoc();
72       // loop over each optional definition
73
Iterator JavaDoc iter = definitions.values().iterator();
74       while (iter.hasNext()) {
75         ModuleDefinition definition = (ModuleDefinition) iter.next();
76         // and create the corresponding optional instance
77
ModuleInstance instance = definition.createInstance();
78         if (instance != null) {
79           addInstance( instance );
80         }
81       }
82     }
83     
84     // add the creation log
85
rootToken.addLog(new ProcessInstanceCreateLog());
86
87     // if this process instance is created in the context of a persistent operation
88
JbpmSession jbpmSession = JbpmSession.getCurrentJbpmSession();
89     if (jbpmSession!=null) {
90       // give this process instance an id
91
jbpmSession.getSession().save(this);
92     }
93
94     // fire the process start event
95
if (rootToken.getNode()!=null) {
96       ExecutionContext executionContext = new ExecutionContext(rootToken);
97       processDefinition.fireEvent(Event.EVENTTYPE_PROCESS_START, executionContext);
98     }
99   }
100
101   // optional module instances
102
/////////////////////////////////////////////////////////////////////////////
103

104   /**
105    * adds the given optional moduleinstance (bidirectional).
106    */

107   public ModuleInstance addInstance(ModuleInstance moduleInstance) {
108     if (moduleInstance == null) throw new IllegalArgumentException JavaDoc("can't add a null moduleInstance to a process instance");
109     if (instances == null) instances = new HashMap JavaDoc();
110     instances.put(moduleInstance.getClass().getName(), moduleInstance);
111     moduleInstance.setProcessInstance(this);
112     return moduleInstance;
113   }
114
115   /**
116    * removes the given optional moduleinstance (bidirectional).
117    */

118   public ModuleInstance removeInstance(ModuleInstance moduleInstance) {
119     ModuleInstance removedModuleInstance = null;
120     if (moduleInstance == null) throw new IllegalArgumentException JavaDoc("can't remove a null moduleInstance from a process instance");
121     if (instances != null) {
122       removedModuleInstance = (ModuleInstance) instances.remove(moduleInstance.getClass().getName());
123       if (removedModuleInstance!=null) {
124         moduleInstance.setProcessInstance(null);
125       }
126     }
127     return removedModuleInstance;
128   }
129
130   /**
131    * looks up an optional module instance by its class.
132    */

133   public ModuleInstance getInstance(Class JavaDoc clazz) {
134     ModuleInstance moduleInstance = null;
135     if ( instances != null ) {
136       moduleInstance = (ModuleInstance) instances.get( clazz.getName() );
137     }
138     
139     if (moduleInstance==null) {
140       if (transientInstances==null) transientInstances = new HashMap JavaDoc();
141       
142       // client requested an instance that is not in the map of instances.
143
// so we can safely assume that the client wants a transient instance
144
moduleInstance = (ModuleInstance) transientInstances.get( clazz.getName() );
145       if (moduleInstance==null) {
146         try {
147           moduleInstance = (ModuleInstance) clazz.newInstance();
148         } catch (Exception JavaDoc e) {
149           e.printStackTrace();
150           throw new RuntimeException JavaDoc("couldn't instantiate transient module '"+clazz.getName()+"' with the default constructor");
151         }
152         transientInstances.put(clazz.getName(), moduleInstance);
153       }
154     }
155
156     return moduleInstance;
157   }
158
159   /**
160    * process instance extension for process variables.
161    */

162   public ContextInstance getContextInstance() {
163     return (ContextInstance) getInstance(ContextInstance.class);
164   }
165
166   /**
167    * process instance extension for managing the tasks and actors.
168    */

169   public TaskMgmtInstance getTaskMgmtInstance() {
170     return (TaskMgmtInstance) getInstance(TaskMgmtInstance.class);
171   }
172
173   /**
174    * process instance extension for logging. Probably you don't need to access
175    * the logging instance directly. Mostly, {@link Token#addLog(ProcessLog)} is
176    * sufficient and more convenient.
177    */

178   public LoggingInstance getLoggingInstance() {
179     return (LoggingInstance) getInstance(LoggingInstance.class);
180   }
181
182   /**
183    * process instance extension for timers.
184    */

185   public SchedulerInstance getSchedulerInstance() {
186     return (SchedulerInstance) getInstance(SchedulerInstance.class);
187   }
188
189
190   // operations ///////////////////////////////////////////////////////////////
191

192   /**
193    * instructs the main path of execution to continue by taking the default
194    * transition on the current node.
195    * @throws IllegalStateException if the token is not active.
196    */

197   public void signal() {
198     if ( hasEnded() ) {
199       throw new IllegalStateException JavaDoc("couldn't signal token : token has ended");
200     }
201     rootToken.signal();
202   }
203
204   /**
205    * instructs the main path of execution to continue by taking the specified
206    * transition on the current node.
207    * @throws IllegalStateException if the token is not active.
208    */

209   public void signal(String JavaDoc transitionName) {
210     if ( hasEnded() ) {
211       throw new IllegalStateException JavaDoc("couldn't signal token : token has ended");
212     }
213     rootToken.signal(transitionName);
214   }
215
216   /**
217    * instructs the main path of execution to continue by taking the specified
218    * transition on the current node.
219    * @throws IllegalStateException if the token is not active.
220    */

221   public void signal( Transition transition ) {
222     if ( hasEnded() ) {
223       throw new IllegalStateException JavaDoc("couldn't signal token : token has ended");
224     }
225     rootToken.signal(transition);
226   }
227
228   /**
229    * ends (=cancels) this process instance and all the tokens in it.
230    */

231   public void end() {
232     // end the main path of execution
233
rootToken.end();
234     
235     if (end==null) {
236       // mark this process instance as ended
237
end = new Date JavaDoc();
238       
239       // fire the process-end event
240
ExecutionContext executionContext = new ExecutionContext(rootToken);
241       processDefinition.fireEvent(Event.EVENTTYPE_PROCESS_END, executionContext);
242       
243       // add the process instance end log
244
rootToken.addLog(new ProcessInstanceEndLog());
245
246       // check if this process was started as a subprocess of a super process
247
if (superProcessToken!=null) {
248         ProcessState processState = (ProcessState) superProcessToken.getNode();
249         processState.notifySubProcessEnd(this);
250       }
251
252       // make sure all the timers for this process instance are cancelled when the process end updates get saved in the database.
253
// see also org.jbpm.db.SchedulerSession.saveTimers(ProcessInstance);
254
getSchedulerInstance().setProcessEnded(true);
255     }
256   }
257
258   // runtime actions //////////////////////////////////////////////////////////
259

260   /**
261    * adds an action to be executed upon a process event in the future.
262    */

263   public RuntimeAction addRuntimeAction( RuntimeAction runtimeAction ) {
264     if (runtimeAction == null) throw new IllegalArgumentException JavaDoc("can't add a null runtimeAction to a process instance");
265     if (runtimeActions == null) runtimeActions = new ArrayList JavaDoc();
266     runtimeActions.add(runtimeAction);
267     runtimeAction.processInstance = this;
268     return runtimeAction;
269   }
270
271   /**
272    * removes a runtime action.
273    */

274   public RuntimeAction removeRuntimeAction( RuntimeAction runtimeAction ) {
275     RuntimeAction removedRuntimeAction = null;
276     if (runtimeAction == null)
277       throw new IllegalArgumentException JavaDoc("can't remove a null runtimeAction from an process instance");
278     if (runtimeActions != null) {
279       if (runtimeActions.remove(runtimeAction)) {
280         removedRuntimeAction = runtimeAction;
281         runtimeAction.processInstance = null;
282       }
283     }
284     return removedRuntimeAction;
285   }
286
287   /**
288    * is the list of all runtime actions.
289    */

290   public List JavaDoc getRuntimeActions() {
291     return runtimeActions;
292   }
293
294   // various information retrieval methods ////////////////////////////////////
295

296   /**
297    * tells if this process instance is still active or not.
298    */

299   public boolean hasEnded() {
300     return ( end != null );
301   }
302   
303   /**
304    * calculates if this process instance has still options to continue.
305    */

306   public boolean isTerminatedImplicitly() {
307     boolean isTerminatedImplicitly = true;
308     if ( end == null ) {
309       isTerminatedImplicitly = rootToken.isTerminatedImplicitly();
310     }
311     return isTerminatedImplicitly;
312   }
313   
314   /**
315    * looks up the token in the tree, specified by the slash-separated token path.
316    * @param tokenPath is a slash-separated name that specifies a token in the tree.
317    * @return the specified token or null if the token is not found.
318    */

319   public Token findToken(String JavaDoc tokenPath) {
320     return ( rootToken!=null ? rootToken.findToken(tokenPath) : null );
321   }
322   
323   // getters and setters //////////////////////////////////////////////////////
324

325   public long getId() {
326     return id;
327   }
328   public Token getRootToken() {
329     return rootToken;
330   }
331   public Date JavaDoc getStart() {
332     return start;
333   }
334   public Date JavaDoc getEnd() {
335     return end;
336   }
337   public Map JavaDoc getInstances() {
338     return instances;
339   }
340   public ProcessDefinition getProcessDefinition() {
341     return processDefinition;
342   }
343   public Token getSuperProcessToken() {
344     return superProcessToken;
345   }
346   public void setSuperProcessToken(Token superProcessToken) {
347     this.superProcessToken = superProcessToken;
348   }
349 }
350
Popular Tags