KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jbpm > graph > def > GraphElement


1 package org.jbpm.graph.def;
2
3 import java.io.*;
4 import java.util.*;
5
6 import org.apache.commons.logging.*;
7 import org.jbpm.graph.exe.*;
8 import org.jbpm.graph.log.ActionLog;
9
10 public abstract class GraphElement implements Serializable {
11   
12   private static final long serialVersionUID = 1L;
13
14   long id = 0;
15   protected String JavaDoc name = null;
16   protected ProcessDefinition processDefinition = null;
17   protected Map events = null;
18   protected List exceptionHandlers = null;
19
20   public GraphElement() {
21   }
22   
23   public GraphElement( String JavaDoc name ) {
24     setName( name );
25   }
26
27   // events ///////////////////////////////////////////////////////////////////
28

29   /**
30    * indicative set of event types supported by this graph element.
31    * this is currently only used by the process designer to know which
32    * event types to show on a given graph element. in process definitions
33    * and at runtime, there are no contstraints on the event-types.
34    */

35   public abstract String JavaDoc[] getSupportedEventTypes();
36
37   /**
38    * gets the events, keyd by eventType (java.lang.String).
39    */

40   public Map getEvents() {
41     return events;
42   }
43
44   public boolean hasEvents() {
45     return ( (events!=null)
46              && (events.size()>0) );
47   }
48
49   public Event getEvent(String JavaDoc eventType) {
50     Event event = null;
51     if (events!=null) {
52       event = (Event) events.get(eventType);
53     }
54     return event;
55   }
56   
57   public boolean hasEvent(String JavaDoc eventType) {
58     boolean hasEvent = false;
59     if (events!=null) {
60       hasEvent = events.containsKey(eventType);
61     }
62     return hasEvent;
63   }
64   
65   public Event addEvent(Event event) {
66     if (event == null) throw new IllegalArgumentException JavaDoc("can't add a null event to a graph element");
67     if (event.getEventType() == null) throw new IllegalArgumentException JavaDoc("can't add an event without an eventType to a graph element");
68     if (events == null) events = new HashMap();
69     events.put(event.getEventType(), event);
70     event.graphElement = this;
71     return event;
72   }
73   
74   public Event removeEvent(Event event) {
75     Event removedEvent = null;
76     if (event == null) throw new IllegalArgumentException JavaDoc("can't remove a null event from a graph element");
77     if (event.getEventType() == null) throw new IllegalArgumentException JavaDoc("can't remove an event without an eventType from a graph element");
78     if (events != null) {
79       removedEvent = (Event) events.remove(event.getEventType());
80       if (removedEvent!=null) {
81         event.graphElement = null;
82       }
83     }
84     return removedEvent;
85   }
86
87   // exception handlers ///////////////////////////////////////////////////////
88

89   /**
90    * is the list of exception handlers associated to this graph element.
91    */

92   public List getExceptionHandlers() {
93     return exceptionHandlers;
94   }
95   
96   public ExceptionHandler addExceptionHandler(ExceptionHandler exceptionHandler) {
97     if (exceptionHandler == null) throw new IllegalArgumentException JavaDoc("can't add a null exceptionHandler to a graph element");
98     if (exceptionHandlers == null) exceptionHandlers = new ArrayList();
99     exceptionHandlers.add(exceptionHandler);
100     exceptionHandler.graphElement = this;
101     return exceptionHandler;
102   }
103   
104   public void removeExceptionHandler(ExceptionHandler exceptionHandler) {
105     if (exceptionHandler == null) throw new IllegalArgumentException JavaDoc("can't remove a null exceptionHandler from an graph element");
106     if (exceptionHandlers != null) {
107       if (exceptionHandlers.remove(exceptionHandler)) {
108         exceptionHandler.graphElement = null;
109       }
110     }
111   }
112
113   public void reorderExceptionHandler(int oldIndex, int newIndex) {
114     if ( (exceptionHandlers!=null)
115          && (Math.min(oldIndex, newIndex)>=0)
116          && (Math.max(oldIndex, newIndex)<exceptionHandlers.size()) ) {
117       Object JavaDoc o = exceptionHandlers.remove(oldIndex);
118       exceptionHandlers.add(newIndex, o);
119     } else {
120       throw new IndexOutOfBoundsException JavaDoc("couldn't reorder element from index '"+oldIndex+"' to index '"+newIndex+"' in exceptionHandler-list '"+exceptionHandlers+"'");
121     }
122   }
123
124   // event handling ///////////////////////////////////////////////////////////
125

126   public void fireEvent(String JavaDoc eventType, ExecutionContext executionContext) {
127     Token token = executionContext.getToken();
128
129     log.debug( "event '"+eventType+"' on '"+this+"' for '"+token+"'" );
130
131     try {
132       executionContext.setEventSource(this);
133       fireAndPropagateEvent(eventType, executionContext);
134     } finally {
135       executionContext.setEventSource(null);
136     }
137   }
138
139   public void fireAndPropagateEvent(String JavaDoc eventType, ExecutionContext executionContext) {
140     // calculate if the event was fired on this element or if it was a propagated event
141
boolean isPropagated = (executionContext.getEventSource()!=this);
142     
143     // execute static actions
144
Event event = getEvent(eventType);
145     if (event!=null) {
146       // update the context
147
executionContext.setEvent(event);
148       // execute the static actions specified in the process definition
149
executeActions(event.getActions(), executionContext, isPropagated);
150     }
151     
152     // execute the runtime actions
153
List runtimeActions = getRuntimeActionsForEvent(executionContext, eventType);
154     executeActions(runtimeActions, executionContext, isPropagated);
155
156     // remove the event from the context
157
executionContext.setEvent(null);
158     
159     // propagate the event to the parent element
160
GraphElement parent = getParent();
161     if (parent!=null) {
162       parent.fireAndPropagateEvent(eventType, executionContext);
163     }
164   }
165
166   private void executeActions(List actions, ExecutionContext executionContext, boolean isPropagated) {
167     if (actions!=null) {
168       Iterator iter = actions.iterator();
169       while (iter.hasNext()) {
170         Action action = (Action) iter.next();
171         if ( action.acceptsPropagatedEvents()
172              || (!isPropagated)
173            ) {
174           Token token = executionContext.getToken();
175
176           // create action log
177
ActionLog actionLog = new ActionLog(action);
178           token.startCompositeLog(actionLog);
179
180           try {
181             // update the execution context
182
executionContext.setAction(action);
183
184             // execute the action
185
log.debug("executing action '"+action+"'");
186             action.execute(executionContext);
187       
188           } catch (Throwable JavaDoc exception) {
189             log.error("action threw exception: "+exception.getMessage(), exception);
190             
191             // log the action exception
192
actionLog.setException(exception);
193       
194             // if an exception handler is available
195
raiseException(exception, executionContext);
196             
197           } finally {
198             executionContext.setAction(null);
199             token.endCompositeLog();
200           }
201         }
202       }
203     }
204   }
205
206   private List getRuntimeActionsForEvent(ExecutionContext executionContext, String JavaDoc eventType) {
207     List runtimeActionsForEvent = null;
208     List runtimeActions = executionContext.getProcessInstance().getRuntimeActions();
209     if (runtimeActions!=null) {
210       Iterator iter = runtimeActions.iterator();
211       while (iter.hasNext()) {
212         RuntimeAction runtimeAction = (RuntimeAction) iter.next();
213         // if the runtime-action action is registered on this element and this eventType
214
if ( (this==runtimeAction.getGraphElement())
215              && (eventType.equals(runtimeAction.getEventType()))
216            ) {
217           // ... add its action to the list of runtime actions
218
if (runtimeActionsForEvent==null) runtimeActionsForEvent = new ArrayList();
219           runtimeActionsForEvent.add(runtimeAction.getAction());
220         }
221       }
222     }
223     return runtimeActionsForEvent;
224   }
225
226 /*
227       // the next instruction merges the actions specified in the process definition with the runtime actions
228       List actions = event.collectActions(executionContext);
229       
230       // loop over all actions of this event
231       Iterator iter = actions.iterator();
232       while (iter.hasNext()) {
233         Action action = (Action) iter.next();
234         executionContext.setAction(action);
235         
236         if ( (!isPropagated)
237              || (action.acceptsPropagatedEvents() ) ) {
238       
239           // create action log
240           ActionLog actionLog = new ActionLog(action);
241           executionContext.getToken().startCompositeLog(actionLog);
242       
243           try {
244             // execute the action
245             action.execute(executionContext);
246       
247           } catch (Throwable exception) {
248             Event.log.error("action threw exception: "+exception.getMessage(), exception);
249             
250             // log the action exception
251             actionLog.setException(exception);
252       
253             // if an exception handler is available
254             event.graphElement.raiseException(exception, executionContext);
255           } finally {
256             executionContext.getToken().endCompositeLog();
257           }
258         }
259       }
260     }
261 */

262
263   /**
264    * throws an ActionException if no applicable exception handler is found.
265    * An ExceptionHandler is searched for in this graph element and then recursively up the
266    * parent hierarchy.
267    * If an exception handler is found, it is applied. If the exception handler does not
268    * throw an exception, the exception is considered handled. Otherwise the search for
269    * an applicable exception handler continues where it left of with the newly thrown
270    * exception.
271    */

272   public void raiseException(Throwable JavaDoc exception, ExecutionContext executionContext) throws DelegationException {
273     boolean isHandled = false;
274     if (exceptionHandlers!=null) {
275       try {
276         ExceptionHandler exceptionHandler = findExceptionHandler(exception);
277         if (exceptionHandler!=null) {
278           executionContext.setException(exception);
279           exceptionHandler.handleException(executionContext);
280           isHandled = true;
281         }
282       } catch (Throwable JavaDoc t) {
283         exception = t;
284       }
285     }
286
287     if (!isHandled) {
288       GraphElement parent = getParent();
289       // if this graph element has a parent
290
if ( (parent!=null)
291            && (parent!=this) ){
292         // action to the parent
293
parent.raiseException(exception, executionContext);
294       } else {
295         // rollback the actions
296
// rollbackActions(executionContext);
297

298         // if there is no parent we need to throw an action exception to the client
299
throw new DelegationException(exception, executionContext);
300       }
301     }
302   }
303
304   protected ExceptionHandler findExceptionHandler(Throwable JavaDoc exception) {
305     ExceptionHandler exceptionHandler = null;
306     
307     if (exceptionHandlers!=null) {
308       Iterator iter = exceptionHandlers.iterator();
309       while (iter.hasNext() && (exceptionHandler==null)) {
310         ExceptionHandler candidate = (ExceptionHandler) iter.next();
311         if (candidate.matches(exception)) {
312           exceptionHandler = candidate;
313         }
314       }
315     }
316     
317     return exceptionHandler;
318   }
319
320   public GraphElement getParent() {
321     return processDefinition;
322   }
323
324   /**
325    * @return all the parents of this graph element ordered by age.
326    */

327   public List getParents() {
328     List parents = new ArrayList();
329     GraphElement parent = getParent();
330     if (parent!=null) {
331       parent.addParentChain(parents);
332     }
333     return parents;
334   }
335
336   /**
337    * @return this graph element plus all the parents ordered by age.
338    */

339   public List getParentChain() {
340     List parents = new ArrayList();
341     this.addParentChain(parents);
342     return parents;
343   }
344
345   private void addParentChain(List parentChain) {
346     parentChain.add(this);
347     GraphElement parent = getParent();
348     if (parent!=null) {
349       parent.addParentChain(parentChain);
350     }
351   }
352   
353   public String JavaDoc toString() {
354     String JavaDoc className = getClass().getName();
355     className = className.substring(className.lastIndexOf('.')+1);
356     if (name!=null) {
357       className = className+"("+name+")";
358     } else {
359       className = className+"("+Integer.toHexString(System.identityHashCode(this))+")";
360     }
361     return className;
362   }
363
364   // getters and setters //////////////////////////////////////////////////////
365

366   public long getId() {
367     return id;
368   }
369   public String JavaDoc getName() {
370     return name;
371   }
372   public void setName( String JavaDoc name ) {
373     this.name = name;
374   }
375
376   public ProcessDefinition getProcessDefinition() {
377     return processDefinition;
378   }
379   public void setProcessDefinition(ProcessDefinition processDefinition) {
380     this.processDefinition = processDefinition;
381   }
382   
383   // logger ///////////////////////////////////////////////////////////////////
384
private static final Log log = LogFactory.getLog(GraphElement.class);
385 }
386
Popular Tags