1 package org.jbpm.graph.def; 2 3 import java.util.ArrayList ; 4 import java.util.Date ; 5 import java.util.HashMap ; 6 import java.util.HashSet ; 7 import java.util.Iterator ; 8 import java.util.List ; 9 import java.util.Map ; 10 import java.util.Set ; 11 12 import org.dom4j.Element; 13 import org.jbpm.graph.action.ActionTypes; 14 import org.jbpm.graph.exe.ExecutionContext; 15 import org.jbpm.graph.exe.Token; 16 import org.jbpm.graph.log.NodeLog; 17 import org.jbpm.jpdl.xml.JpdlXmlReader; 18 import org.jbpm.jpdl.xml.Parsable; 19 20 public class Node extends GraphElement implements Parsable { 21 22 private static final long serialVersionUID = 1L; 23 24 protected List leavingTransitions = null; 25 private transient Map leavingTransitionMap = null; 26 protected Set arrivingTransitions = null; 27 protected Action action = null; 28 protected SuperState superState = null; 29 30 31 33 public static final String [] supportedEventTypes = new String []{Event.EVENTTYPE_NODE_ENTER,Event.EVENTTYPE_NODE_LEAVE,Event.EVENTTYPE_BEFORE_SIGNAL,Event.EVENTTYPE_AFTER_SIGNAL}; 34 public String [] getSupportedEventTypes() { 35 return supportedEventTypes; 36 } 37 38 40 43 public Node() { 44 } 45 46 49 public Node(String name) { 50 super(name); 51 } 52 53 public void read(Element nodeElement, JpdlXmlReader jpdlXmlReader) { 54 action = jpdlXmlReader.readSingleAction(nodeElement); 55 } 56 57 public void write(Element nodeElement) { 58 if (action!=null) { 59 String actionName = ActionTypes.getActionName(action.getClass()); 60 Element actionElement = nodeElement.addElement(actionName); 61 action.write(actionElement); 62 } 63 } 64 65 67 public List getLeavingTransitions() { 68 return leavingTransitions; 69 } 70 71 74 public Map getLeavingTransitionsMap() { 75 if ( (leavingTransitionMap==null) 76 && (leavingTransitions!=null) ){ 77 leavingTransitionMap = new HashMap (); 79 Iterator iter = leavingTransitions.iterator(); 80 while (iter.hasNext()) { 81 Transition leavingTransition = (Transition) iter.next(); 82 leavingTransitionMap.put(leavingTransition.getName(), leavingTransition); 83 } 84 } 85 return leavingTransitionMap; 86 } 87 88 92 public Transition addLeavingTransition(Transition leavingTransition) { 93 if (leavingTransition == null) throw new IllegalArgumentException ("can't add a null leaving transition to an node"); 94 if (leavingTransitions == null) leavingTransitions = new ArrayList (); 95 leavingTransitions.add(leavingTransition); 96 leavingTransition.from = this; 97 leavingTransitionMap = null; 98 return leavingTransition; 99 } 100 101 105 public void removeLeavingTransition(Transition leavingTransition) { 106 if (leavingTransition == null) throw new IllegalArgumentException ("can't remove a null leavingTransition from an node"); 107 if (leavingTransitions != null) { 108 if (leavingTransitions.remove(leavingTransition)) { 109 leavingTransition.from = null; 110 leavingTransitionMap = null; 111 } 112 } 113 } 114 115 120 public boolean hasLeavingTransition(String transitionName) { 121 if (leavingTransitions==null) return false; 122 return getLeavingTransitionsMap().containsKey(transitionName); 123 } 124 125 129 public Transition getLeavingTransition(String transitionName) { 130 Transition transition = null; 131 if (leavingTransitions!=null) { 132 transition = (Transition) getLeavingTransitionsMap().get(transitionName); 133 } 134 if ( (transition==null) 135 && (superState!=null) 136 ) { 137 transition = superState.getLeavingTransition(transitionName); 138 } 139 return transition; 140 } 141 142 145 public boolean hasNoLeavingTransitions() { 146 return ( ( (leavingTransitions == null) 147 || (leavingTransitions.size() == 0) ) 148 && ( (superState==null) 149 || (superState.hasNoLeavingTransitions() ) ) ); 150 } 151 152 155 public String generateNextLeavingTransitionName() { 156 String name = null; 157 if (leavingTransitions!=null) { 158 if (!containsName(leavingTransitions, null)) { 159 name = null; 160 } else { 161 int n = 1; 162 while (containsName(leavingTransitions, Integer.toString(n))) n++; 163 name = Integer.toString(n); 164 } 165 } 166 return name; 167 } 168 169 private boolean containsName(List leavingTransitions, String name) { 170 Iterator iter = leavingTransitions.iterator(); 171 while (iter.hasNext()) { 172 Transition transition = (Transition) iter.next(); 173 if ( (name==null) && (transition.getName()==null) ) { 174 return true; 175 } else if ( (name!=null) && (name.equals(transition.getName())) ) { 176 return true; 177 } 178 } 179 return false; 180 } 181 182 184 187 public Transition getDefaultLeavingTransition() { 188 Transition defaultTransition = null; 189 if ( (leavingTransitions!=null) 190 && (leavingTransitions.size()>0) ) { 191 defaultTransition = (Transition) leavingTransitions.get(0); 192 } else if ( superState!=null ){ 193 defaultTransition = superState.getDefaultLeavingTransition(); 194 } 195 return defaultTransition; 196 } 197 198 201 public void reorderLeavingTransition( int oldIndex, int newIndex ) { 202 if ( (leavingTransitions!=null) 203 && (Math.min(oldIndex, newIndex)>=0) 204 && (Math.max(oldIndex, newIndex)<leavingTransitions.size()) ) { 205 Object o = leavingTransitions.remove(oldIndex); 206 leavingTransitions.add(newIndex, o); 207 } 208 } 209 210 public List getLeavingTransitionsList() { 211 return leavingTransitions; 212 } 213 214 216 219 public Set getArrivingTransitions() { 220 return arrivingTransitions; 221 } 222 223 228 public Transition addArrivingTransition(Transition arrivingTransition) { 229 if (arrivingTransition == null) throw new IllegalArgumentException ("can't add a null arrivingTransition to a node"); 230 if (arrivingTransitions == null) arrivingTransitions = new HashSet (); 231 arrivingTransitions.add(arrivingTransition); 232 arrivingTransition.to = this; 233 return arrivingTransition; 234 } 235 236 241 public void removeArrivingTransition(Transition arrivingTransition) { 242 if (arrivingTransition == null) throw new IllegalArgumentException ("can't remove a null arrivingTransition from a node"); 243 if (arrivingTransitions != null) { 244 if (arrivingTransitions.remove(arrivingTransition)) { 245 arrivingTransition.to = null; 246 } 247 } 248 } 249 250 252 256 public GraphElement getParent() { 257 GraphElement parent = processDefinition; 258 if (superState!=null) parent = superState; 259 return parent; 260 } 261 262 264 267 public void enter(ExecutionContext executionContext) { 268 Token token = executionContext.getToken(); 269 270 token.setNode(this); 272 273 fireEvent(Event.EVENTTYPE_NODE_ENTER, executionContext); 275 276 token.setNodeEnter(new Date ()); 278 279 executionContext.setTransition(null); 281 executionContext.setTransitionSource(null); 282 283 execute(executionContext); 285 } 286 287 290 public void execute(ExecutionContext executionContext) { 291 if (action!=null) { 293 try { 294 action.execute(executionContext); 296 297 } catch (Throwable exception) { 298 raiseException(exception, executionContext); 300 } 301 302 } else { 303 leave(executionContext); 306 } 307 } 308 309 312 public void leave(ExecutionContext executionContext) { 313 leave(executionContext, getDefaultLeavingTransition()); 314 } 315 316 319 public void leave(ExecutionContext executionContext, String transitionName) { 320 Transition transition = getLeavingTransition(transitionName); 321 if (transition==null) { 322 throw new RuntimeException ("transition '"+transitionName+"' is not a leaving transition of node '"+this+"'"); 323 } 324 leave(executionContext, transition); 325 } 326 327 330 public void leave(ExecutionContext executionContext, Transition transition) { 331 if (transition==null) throw new RuntimeException ("can't leave node '"+this+"' without leaving transition"); 332 Token token = executionContext.getToken(); 333 token.setNode(this); 334 executionContext.setTransition(transition); 335 336 fireEvent(Event.EVENTTYPE_NODE_LEAVE, executionContext); 338 339 if (token.getNodeEnter()!=null) { 341 token.addLog(new NodeLog(this, token.getNodeEnter(), new Date ())); 342 } 343 344 executionContext.setTransitionSource(this); 347 348 transition.take(executionContext); 350 } 351 352 354 public ProcessDefinition getProcessDefinition() { 355 ProcessDefinition pd = this.processDefinition; 356 if (superState!=null) { 357 pd = superState.getProcessDefinition(); 358 } 359 return pd; 360 } 361 362 366 public void setName(String name) { 367 if (isDifferent(this.name, name)) { 368 String oldName = this.name; 369 if (superState!=null) { 370 if ( superState.hasNode(name) ) { 371 throw new IllegalArgumentException ("couldn't set name '"+name+"' on node '"+this+"'cause the superState of this node has already another child node with the same name"); 372 } 373 Map nodes = superState.getNodesMap(); 374 nodes.remove(oldName); 375 nodes.put(name,this); 376 } else if (processDefinition!=null) { 377 if ( processDefinition.hasNode(name) ) { 378 throw new IllegalArgumentException ("couldn't set name '"+name+"' on node '"+this+"'cause the process definition of this node has already another node with the same name"); 379 } 380 Map nodeMap = processDefinition.getNodesMap(); 381 nodeMap.remove(oldName); 382 nodeMap.put(name,this); 383 } 384 this.name = name; 385 } 386 } 387 388 private boolean isDifferent(String name1, String name2) { 389 if ((name1!=null) 390 && (name1.equals(name2))) { 391 return false; 392 } else if ( (name1==null) 393 && (name2==null) ) { 394 return false; 395 } 396 return true; 397 } 398 399 402 public String getFullyQualifiedName() { 403 String fullyQualifiedName = name; 404 if (superState!=null) { 405 fullyQualifiedName = superState.getFullyQualifiedName()+"/"+name; 406 } 407 return fullyQualifiedName; 408 } 409 410 412 public SuperState getSuperState() { 413 return superState; 414 } 415 public Action getAction() { 416 return action; 417 } 418 public void setAction(Action action) { 419 this.action = action; 420 } 421 422 } 425 | Popular Tags |