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 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 name ) { 24 setName( name ); 25 } 26 27 29 35 public abstract String [] getSupportedEventTypes(); 36 37 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 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 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 ("can't add a null event to a graph element"); 67 if (event.getEventType() == null) throw new IllegalArgumentException ("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 ("can't remove a null event from a graph element"); 77 if (event.getEventType() == null) throw new IllegalArgumentException ("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 89 92 public List getExceptionHandlers() { 93 return exceptionHandlers; 94 } 95 96 public ExceptionHandler addExceptionHandler(ExceptionHandler exceptionHandler) { 97 if (exceptionHandler == null) throw new IllegalArgumentException ("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 ("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 o = exceptionHandlers.remove(oldIndex); 118 exceptionHandlers.add(newIndex, o); 119 } else { 120 throw new IndexOutOfBoundsException ("couldn't reorder element from index '"+oldIndex+"' to index '"+newIndex+"' in exceptionHandler-list '"+exceptionHandlers+"'"); 121 } 122 } 123 124 126 public void fireEvent(String 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 eventType, ExecutionContext executionContext) { 140 boolean isPropagated = (executionContext.getEventSource()!=this); 142 143 Event event = getEvent(eventType); 145 if (event!=null) { 146 executionContext.setEvent(event); 148 executeActions(event.getActions(), executionContext, isPropagated); 150 } 151 152 List runtimeActions = getRuntimeActionsForEvent(executionContext, eventType); 154 executeActions(runtimeActions, executionContext, isPropagated); 155 156 executionContext.setEvent(null); 158 159 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 ActionLog actionLog = new ActionLog(action); 178 token.startCompositeLog(actionLog); 179 180 try { 181 executionContext.setAction(action); 183 184 log.debug("executing action '"+action+"'"); 186 action.execute(executionContext); 187 188 } catch (Throwable exception) { 189 log.error("action threw exception: "+exception.getMessage(), exception); 190 191 actionLog.setException(exception); 193 194 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 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 ( (this==runtimeAction.getGraphElement()) 215 && (eventType.equals(runtimeAction.getEventType())) 216 ) { 217 if (runtimeActionsForEvent==null) runtimeActionsForEvent = new ArrayList(); 219 runtimeActionsForEvent.add(runtimeAction.getAction()); 220 } 221 } 222 } 223 return runtimeActionsForEvent; 224 } 225 226 262 263 272 public void raiseException(Throwable 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 t) { 283 exception = t; 284 } 285 } 286 287 if (!isHandled) { 288 GraphElement parent = getParent(); 289 if ( (parent!=null) 291 && (parent!=this) ){ 292 parent.raiseException(exception, executionContext); 294 } else { 295 298 throw new DelegationException(exception, executionContext); 300 } 301 } 302 } 303 304 protected ExceptionHandler findExceptionHandler(Throwable 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 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 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 toString() { 354 String 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 366 public long getId() { 367 return id; 368 } 369 public String getName() { 370 return name; 371 } 372 public void setName( String 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 private static final Log log = LogFactory.getLog(GraphElement.class); 385 } 386 | Popular Tags |