KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jbpm > bpel > def > Activity


1 package org.jbpm.bpel.def;
2
3 import java.util.Collection JavaDoc;
4 import java.util.HashSet JavaDoc;
5 import java.util.Iterator JavaDoc;
6
7 import org.jbpm.graph.def.*;
8 import org.jbpm.graph.exe.ExecutionContext;
9 import org.jbpm.graph.exe.Token;
10
11 import org.jbpm.bpel.data.def.Snippet;
12 import org.jbpm.bpel.exe.LinkInstance;
13 import org.jbpm.bpel.exe.ScopeInstance;
14 import org.jbpm.bpel.xml.util.DatatypeUtil;
15
16 /**
17  * Represents a BPEL activity.
18  * @see "WS-BPEL 2.0 §11.1, §11.2"
19  * @author Juan Cantú
20  * @version $Revision: 1.11 $ $Date: 2005/06/23 02:22:46 $
21  */

22 public abstract class Activity extends Node {
23   
24   private Boolean JavaDoc suppressJoinFailure;
25   private Snippet joinCondition;
26   private Collection JavaDoc sources;
27   private Collection JavaDoc targets;
28   protected CompositeActivity compositeActivity;
29   
30   public Activity() {
31   }
32
33   public Activity(String JavaDoc name) {
34     super(name);
35   }
36   
37   public void accept(BpelVisitor visitor) {
38     //nothing is done by default behavior
39
}
40   
41   // jbpm override /////////////////////////////////////////////////////////////////////////////
42

43   /** {@inheritDoc}
44    * Prevents the activity from being executed if the activity has target links and they are
45    * not yet solved.
46    */

47   public void enter(ExecutionContext executionContext) {
48     Token token = executionContext.getToken();
49
50     // update the runtime context information
51
token.setNode(this);
52
53     // fire the enter-node event for this node
54
fireEvent(Event.EVENTTYPE_NODE_ENTER, executionContext);
55
56     // remove the transition references from the runtime context
57
executionContext.setTransition(null);
58     executionContext.setTransitionSource(null);
59
60     // if execution of this node is not dependent on links
61
if ( targets == null || targets.isEmpty() || areLinksReached(executionContext.getToken()) ) {
62       // execute the node
63
execute(executionContext);
64     } // else wait for the targets completion before continuing the execution
65
}
66   
67   /**
68    * {@inheritDoc}
69    * If the activity has source targets their status is solved before carrying
70    * on with the process execution.
71    */

72   public void leave(ExecutionContext executionContext) {
73     if(sources != null) {
74       for(Iterator JavaDoc it = sources.iterator(); it.hasNext();) {
75         Link aSource = (Link) it.next();
76         aSource.execute(executionContext);
77       }
78     }
79     Transition leavingTransition = getDefaultLeavingTransition();
80     if (leavingTransition != null) {
81       // the execution token is passed
82
leave(executionContext, leavingTransition);
83     }
84     else {
85       Token token = executionContext.getToken();
86       token.setNode(this);
87       // fire the leave-node event for this node
88
fireEvent(Event.EVENTTYPE_NODE_LEAVE, executionContext);
89       // complete the scope instance associated with the token
90
ScopeInstance.get(token).completed();
91     }
92   }
93
94   /**
95    * is the {@link CompositeActivity} or the {@link BpelDefinition} in which this
96    * activity is contained.
97    */

98   public GraphElement getParent() {
99     return getCompositeActivity();
100   }
101   
102   public ProcessDefinition getProcessDefinition() {
103     return compositeActivity.getProcessDefinition();
104   }
105   
106   public String JavaDoc toString() {
107     String JavaDoc className = getClass().getName();
108     className = className.substring(className.lastIndexOf('.')+1);
109     String JavaDoc activityName = getName();
110     if (activityName!=null) {
111       className = className+"("+activityName+")";
112     } else {
113       className = className+"("+Integer.toHexString(System.identityHashCode(this))+")";
114     }
115     return className;
116   }
117   
118   // behaviour methods /////////////////////////////////////////////////////////////////////////////
119

120   /**
121    * Called when the execution of an activity wants to be skipped.
122    * If the activity has source links, they are set to a negative status
123    * before carrying on with the process execution.
124    */

125   public void skip(ExecutionContext context) {
126     setNegativeLinkStatus(context.getToken());
127     leave(context, getDefaultLeavingTransition());
128   }
129   
130   protected void setNegativeLinkStatus(Token token) {
131     if(sources != null) {
132       for(Iterator JavaDoc it = getSources().iterator(); it.hasNext();) {
133         Link link = (Link) it.next();
134         link.setNegativeStatus(token);
135       }
136     }
137   }
138   
139   /**
140    * Checks if the activity is ready to continue its execution. This depends on:
141    * a) having determined the status of all the target links.
142    * b) lacking of a join condition or having a positive result of its evaluation
143    * When this evaluation is negative and suppressJoinFailure=yes, this operation
144    * will skip the activity execution and carry on with the remaining process flow
145    * before returning the result.
146    * @see "WS-BPEL 2.0 §12.5.2"
147    */

148   protected boolean areLinksReached(Token token) {
149     if(!linksReady(token)) {
150       return false;
151     }
152     
153     //evaluate condition for the activity
154
if(evaluateJoinCondition(token)) {
155       return true;
156     }
157     else if(suppressJoinFailure()) {
158       ExecutionContext context = new ExecutionContext(token);
159       skip(context);
160       return false;
161     }
162     else {
163         throw new RuntimeException JavaDoc("join failure");
164     }
165   }
166   
167   private boolean linksReady(Token token) {
168     for(Iterator JavaDoc it = getTargets().iterator(); it.hasNext();) {
169       String JavaDoc miName = ((Link) it.next()).getName();
170       if(LinkInstance.get(token, miName).getReached() == null) {
171         return false;
172       }
173     }
174     
175     return true;
176   }
177
178   private boolean evaluateJoinCondition(Token token) {
179     Snippet condition = getJoinCondition();
180     if (condition != null) {
181       return DatatypeUtil.toBoolean(condition.getScript().evaluate(token)).booleanValue();
182     }
183
184     for(Iterator JavaDoc it = getTargets().iterator(); it.hasNext();) {
185       /* if the explicit join condition is missing, the implicit condition
186        * requires the status of at least one incoming link target be positive*/

187       LinkInstance mi = LinkInstance.get(token, ((Link) it.next()).getName());
188       if(mi.getReached().equals(Boolean.TRUE)) {
189         return true;
190       }
191     }
192     return false;
193   }
194   
195   //standard attributes and elements /////////////////////////////////////////////////////////////////////////////
196

197   public Snippet getJoinCondition() {
198     return joinCondition;
199   }
200   
201   public void setJoinCondition(Snippet joinCondition) {
202     this.joinCondition = joinCondition;
203   }
204   
205   public Boolean JavaDoc getSuppressJoinFailure() {
206     return suppressJoinFailure;
207   }
208   
209   
210   public void setSuppressJoinFailure(Boolean JavaDoc suppressJoinFailure) {
211     this.suppressJoinFailure = suppressJoinFailure;
212   }
213
214   public boolean suppressJoinFailure() {
215     Boolean JavaDoc suppress = getSuppressJoinFailure();
216     CompositeActivity parent = getCompositeActivity();
217     
218     if(suppress != null) {
219       return suppress.booleanValue();
220     }
221
222     return parent.suppressJoinFailure();
223   }
224
225   public Collection JavaDoc getTargets() {
226     return targets;
227   }
228   
229   /**
230    * creates a bidirection relation between this activity and the given target link.
231    * @throws IllegalArgumentException if target is null.
232    */

233   public void addTarget(Link link) {
234     if (link == null) throw new IllegalArgumentException JavaDoc("can't add a null target to an activity");
235     if (targets == null) targets = new HashSet JavaDoc();
236     targets.add(link);
237     link.target = this;
238   }
239
240   /**
241    * removes the bidirection relation between this activity and the given target link.
242    * @throws IllegalArgumentException if target is null.
243    */

244   public void removeTarget(Link link) {
245     if (link == null) throw new IllegalArgumentException JavaDoc("can't remove a null leavingTransition from an node");
246     if (link != null) {
247       if (targets.remove(link)) {
248         link.target = null;
249       }
250     }
251   }
252
253   /**
254    * retrieves a target by name.
255    */

256   public Link getTarget(String JavaDoc linkName) {
257     if(targets != null) {
258       for(Iterator JavaDoc it = targets.iterator(); it.hasNext();) {
259         Link aTarget = (Link) it.next();
260         if (linkName.equals(aTarget.getName())) return aTarget;
261       }
262     }
263     return null;
264   }
265
266   public Collection JavaDoc getSources() {
267     return sources;
268   }
269   
270   /**
271    * creates a bidirection relation between this activity and the given source link.
272    * @throws IllegalArgumentException if source is null.
273    */

274   public void addSource(Link link) {
275     if (link == null) throw new IllegalArgumentException JavaDoc("can't add a null source to an activity");
276     if (sources == null) sources = new HashSet JavaDoc();
277     sources.add(link);
278     link.source = this;
279   }
280   
281   /**
282    * removes the bidirection relation between this activity and the given source link.
283    * @throws IllegalArgumentException if source is null.
284    */

285   public void removeSource(Link link) {
286     if (link == null) throw new IllegalArgumentException JavaDoc("can't remove a null leavingTransition from an node");
287     if (link != null) {
288       if (sources.remove(link)) {
289         link.source = null;
290       }
291     }
292   }
293
294   /**
295    * retrieves a source by name.
296    */

297   public Link getSource(String JavaDoc linkName) {
298     for(Iterator JavaDoc it = sources.iterator(); it.hasNext();) {
299       Link aSource = (Link) it.next();
300       if (linkName.equals(aSource.getName())) return aSource;
301     }
302     return null;
303   }
304   
305   // parent relationships /////////////////////////////////////////////////////////////////////////////
306

307   public BpelDefinition getBpelDefinition() {
308     return (BpelDefinition) getProcessDefinition();
309   }
310   
311   public Scope getScope() {
312     return compositeActivity instanceof Scope ? (Scope)compositeActivity
313                                               : compositeActivity.getScope();
314   }
315   
316   public CompositeActivity getCompositeActivity() {
317     return compositeActivity;
318   }
319   
320   // utility methods /////////////////////////////////////////////////////////////////////////////
321

322   /**
323    * This method mirrors the defaultLeavingTransition method to ease the
324    * access of nodes with a single incoming transition. Its important to notice
325    * that the implementation of the standard bpel activities only have one incoming
326    * and one outgoing transition.
327    */

328   public Transition getDefaultArrivingTransition() {
329     return (Transition) getArrivingTransitions().iterator().next();
330   }
331   
332   /**
333    * An activity is initial if its position in the given process guarantees
334    * that there is no basic activity that logically precedes it in the behavior
335    * of the process
336    * @see "WS-BPEL 2.0 §6.5"
337    */

338   public boolean isInitial() {
339     CompositeActivity parent = getCompositeActivity();
340     
341     if(parent == null) {
342       return true;
343     }
344     else if (parent.isInitial()) {
345       return parent.isChildInitial(this);
346     }
347     else {
348       return false;
349     }
350   }
351   
352   /**
353    * Connects a node to another one by creating an implcit transition
354    * between them.
355    */

356   public void connect(Node to) {
357     // create an implicit transition
358
Transition transition = new Transition();
359     addLeavingTransition(transition);
360     to.addArrivingTransition(transition);
361   }
362   
363   public boolean isConnected(Node to) {
364     if(leavingTransitions != null && to.getArrivingTransitions() != null) {
365       for(Iterator JavaDoc it = to.getArrivingTransitions().iterator(); it.hasNext();)
366         if(leavingTransitions.contains(it.next())) return true;
367     }
368     
369     return false;
370   }
371   
372   /**
373    * Disconnects a node from another one by retriving its implicit transition
374    */

375   public void disconnect(Node to) {
376     Transition removedTransition = null;
377     
378     for(Iterator JavaDoc it = to.getArrivingTransitions().iterator(); it.hasNext();) {
379       Transition arrivingTransition = (Transition) it.next();
380       if(leavingTransitions.remove(arrivingTransition)) {
381         removedTransition = arrivingTransition;
382         break;
383       }
384     }
385     
386     if(removedTransition != null) to.removeArrivingTransition(removedTransition);
387   }
388 }
Popular Tags