KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jbpm > graph > node > Fork


1 package org.jbpm.graph.node;
2
3 import java.util.ArrayList JavaDoc;
4 import java.util.Collection JavaDoc;
5 import java.util.Iterator JavaDoc;
6 import java.util.List JavaDoc;
7 import java.util.Map JavaDoc;
8
9 import org.dom4j.Element;
10 import org.jbpm.db.JbpmSession;
11 import org.jbpm.graph.action.Script;
12 import org.jbpm.graph.def.Node;
13 import org.jbpm.graph.exe.ExecutionContext;
14 import org.jbpm.graph.exe.Token;
15 import org.jbpm.jpdl.xml.JpdlXmlReader;
16 import org.jbpm.jpdl.xml.Parsable;
17
18 /**
19  * specifies configurable fork behaviour.
20  *
21  * <p>if this fork behaviour is not sufficient for your needs, consider
22  * writing your own custom TokenHandler.
23  * </p>
24  *
25  * <p>this forkhandler can be configured in 3 ways :
26  * <ul>
27  * <li>without configuration : in that case the fork will launch one
28  * new sub-token over each of the leaving tranisions of the fork
29  * node.
30  * </li>
31  * <li>a script : can be used to calculate a collection of transition
32  * names at runtime. if a script is configured, the script must have
33  * exactly one variable with 'write' access. that variable
34  * should be assigned a java.util.Collection in the script
35  * expression.
36  * </li>
37  * </ul>
38  * </p>
39  */

40 public class Fork extends Node implements Parsable {
41
42   private static final long serialVersionUID = 1L;
43
44   /**
45    * a script that calculates the transitionNames at runtime.
46    */

47   private Script script = null;
48
49   public Fork() {
50   }
51
52   public Fork(String JavaDoc name) {
53     super(name);
54   }
55
56   public void read(Element forkElement, JpdlXmlReader jpdlReader) {
57     Element scriptElement = forkElement.element("script");
58     if (scriptElement!=null) {
59       script = new Script();
60       script.read(scriptElement, jpdlReader);
61     }
62   }
63
64   public void execute(ExecutionContext executionContext) {
65     Token token = executionContext.getToken();
66     Node forkNode = token.getNode();
67     
68     // phase one: collect all the transitionNames
69
Collection JavaDoc transitionNames = null;
70     List JavaDoc forkedTokens = new ArrayList JavaDoc();
71
72     // by default, the fork spawns a token for each leaving transition
73
if (script==null) {
74       transitionNames = forkNode.getLeavingTransitionsMap().keySet();
75
76     } else { // a script is specified
77
// if a script is specified, use that script to calculate the set
78
// of leaving transitions to be used for forking tokens.
79
Map JavaDoc outputMap = script.eval(token);
80       if (outputMap.size()==1) {
81         Object JavaDoc result = outputMap.values().iterator().next();
82         if (result instanceof Collection JavaDoc) {
83           transitionNames = (Collection JavaDoc) result;
84         }
85       }
86       if (transitionNames==null) {
87         throw new RuntimeException JavaDoc("script for fork '"+name+"' should produce one collection (in one writable variable): "+transitionNames);
88       }
89     }
90     
91     // phase two: create forked tokens for the collected transition names
92
Iterator JavaDoc iter = transitionNames.iterator();
93     while (iter.hasNext()) {
94       String JavaDoc transitionName = (String JavaDoc) iter.next();
95       forkedTokens.add(createForkedToken(token, transitionName));
96     }
97
98     // phase three: launch child tokens from the fork over the given transitions
99
iter = forkedTokens.iterator();
100     while( iter.hasNext() ) {
101       ForkedToken forkedToken = (ForkedToken) iter.next();
102       Token childToken = forkedToken.token;
103       String JavaDoc leavingTransitionName = forkedToken.leavingTransitionName;
104       ExecutionContext childExecutionContext = new ExecutionContext(childToken);
105       if (leavingTransitionName!=null) {
106         leave(childExecutionContext, leavingTransitionName);
107       } else {
108         leave(childExecutionContext);
109       }
110     }
111   }
112
113   protected ForkedToken createForkedToken(Token parent, String JavaDoc transitionName) {
114     // instantiate the new token
115
Token childToken = new Token(parent, getTokenName(parent, transitionName));
116
117     // if there is persistency
118
JbpmSession jbpmSession = JbpmSession.getCurrentJbpmSession();
119     if (jbpmSession!=null) {
120       // give the childToken an id
121
jbpmSession.getSession().save(childToken);
122     }
123
124     // create a forked token
125
ForkedToken forkedToken = null;
126     forkedToken = new ForkedToken(childToken, transitionName);
127     
128     return forkedToken;
129   }
130
131   protected String JavaDoc getTokenName(Token parent, String JavaDoc transitionName) {
132     String JavaDoc tokenName = null;
133     if ( transitionName != null ) {
134       if ( ! parent.hasChild( transitionName ) ) {
135         tokenName = transitionName;
136       } else {
137         int i = 2;
138         tokenName = transitionName + Integer.toString( i );
139         while ( parent.hasChild( tokenName ) ) {
140           i++;
141           tokenName = transitionName + Integer.toString( i );
142         }
143       }
144     } else { // no transition name
145
int size = ( parent.getChildren()!=null ? parent.getChildren().size()+1 : 1 );
146       tokenName = Integer.toString(size);
147     }
148     return tokenName;
149   }
150
151   public Script getScript() {
152     return script;
153   }
154   public void setScript(Script script) {
155     this.script = script;
156   }
157   
158   private static class ForkedToken {
159     Token token = null;
160     String JavaDoc leavingTransitionName = null;
161     public ForkedToken(Token token, String JavaDoc leavingTransitionName) {
162       this.token = token;
163       this.leavingTransitionName = leavingTransitionName;
164     }
165   }
166 }
167
Popular Tags