1 package org.jbpm.graph.def; 2 3 import java.io.IOException ; 4 import java.io.InputStream ; 5 import java.io.InputStreamReader ; 6 import java.io.Reader ; 7 import java.io.StringReader ; 8 import java.util.ArrayList ; 9 import java.util.HashMap ; 10 import java.util.Iterator ; 11 import java.util.List ; 12 import java.util.Map ; 13 import java.util.Properties ; 14 import java.util.StringTokenizer ; 15 import java.util.zip.ZipInputStream ; 16 17 import org.jbpm.context.def.ContextDefinition; 18 import org.jbpm.file.def.FileDefinition; 19 import org.jbpm.graph.exe.ProcessInstance; 20 import org.jbpm.graph.node.ProcessFactory; 21 import org.jbpm.graph.node.StartState; 22 import org.jbpm.instantiation.ClassLoaderUtil; 23 import org.jbpm.jpdl.par.ProcessArchive; 24 import org.jbpm.jpdl.xml.JpdlXmlReader; 25 import org.jbpm.module.def.ModuleDefinition; 26 import org.jbpm.taskmgmt.def.TaskMgmtDefinition; 27 28 public class ProcessDefinition extends GraphElement implements NodeCollection { 29 30 private static final long serialVersionUID = 1L; 31 32 protected int version = -1; 33 protected boolean isTerminationImplicit = false; 34 protected StartState startState = null; 35 protected List nodes = null; 36 private transient Map nodesMap = null; 37 protected Map actions = null; 38 protected Map definitions = null; 39 40 41 43 public static final String [] supportedEventTypes = new String []{ 44 Event.EVENTTYPE_PROCESS_START, 45 Event.EVENTTYPE_PROCESS_END, 46 Event.EVENTTYPE_NODE_ENTER, 47 Event.EVENTTYPE_NODE_LEAVE, 48 Event.EVENTTYPE_TASK_CREATE, 49 Event.EVENTTYPE_TASK_ASSIGN, 50 Event.EVENTTYPE_TASK_START, 51 Event.EVENTTYPE_TASK_END, 52 Event.EVENTTYPE_TRANSITION, 53 Event.EVENTTYPE_BEFORE_SIGNAL, 54 Event.EVENTTYPE_AFTER_SIGNAL, 55 Event.EVENTTYPE_SUPERSTATE_ENTER, 56 Event.EVENTTYPE_SUPERSTATE_LEAVE, 57 Event.EVENTTYPE_SUBPROCESS_CREATED, 58 Event.EVENTTYPE_SUBPROCESS_END, 59 Event.EVENTTYPE_TIMER 60 }; 61 public String [] getSupportedEventTypes() { 62 return supportedEventTypes; 63 } 64 65 67 public ProcessDefinition() { 68 this.processDefinition = this; 69 } 70 71 public static ProcessDefinition createNewProcessDefinition() { 72 ProcessDefinition processDefinition = new ProcessDefinition(); 73 74 Properties defaultModulesProperties = ClassLoaderUtil.getProperties("jbpm.default.modules.properties", "org/jbpm/graph/def"); 76 Iterator iter = defaultModulesProperties.keySet().iterator(); 77 while (iter.hasNext()) { 78 String moduleClassName = (String ) iter.next(); 79 try { 80 ModuleDefinition moduleDefinition = (ModuleDefinition) ClassLoaderUtil.loadClass(moduleClassName).newInstance(); 81 processDefinition.addDefinition(moduleDefinition); 82 83 } catch (Exception e) { 84 e.printStackTrace(); 85 throw new RuntimeException ("couldn't instantiate default module '"+moduleClassName+"'", e); 86 } 87 } 88 return processDefinition; 89 } 90 91 public ProcessDefinition(String name) { 92 this.processDefinition = this; 93 this.name = name; 94 } 95 96 public ProcessDefinition(String [] nodes, String [] transitions) { 97 this.processDefinition = this; 98 ProcessFactory.addNodesAndTransitions(this, nodes, transitions); 99 } 100 101 public ProcessInstance createProcessInstance() { 102 return new ProcessInstance(this); 103 } 104 105 public void setProcessDefinition(ProcessDefinition processDefinition) { 106 if (processDefinition!=this) { 107 throw new RuntimeException ("can't set the process-definition-property of a process defition to something else then a self-reference"); 108 } 109 } 110 111 113 117 public static ProcessDefinition parseXmlString(String xml) { 118 StringReader stringReader = new StringReader (xml); 119 JpdlXmlReader jpdlReader = new JpdlXmlReader(stringReader); 120 return jpdlReader.readProcessDefinition(); 121 } 122 123 127 public static ProcessDefinition parseXmlResource(String xmlResource) { 128 return parseXmlInputStream(ClassLoaderUtil.getStream(xmlResource)); 129 } 130 131 135 public static ProcessDefinition parseXmlInputStream(InputStream inputStream) { 136 return parseXmlReader(new InputStreamReader (inputStream)); 137 } 138 139 143 public static ProcessDefinition parseXmlReader(Reader reader) { 144 JpdlXmlReader jpdlReader = new JpdlXmlReader(reader); 145 return jpdlReader.readProcessDefinition(); 146 } 147 148 152 public static ProcessDefinition parseParZipInputStream(ZipInputStream zipInputStream) { 153 try { 154 return new ProcessArchive(zipInputStream).parseProcessDefinition(); 155 } catch (IOException e) { 156 throw new RuntimeException ("couldn't parse par zip file zipInputStream", e); 157 } 158 } 159 160 164 public static ProcessDefinition parseParResource(String parResource) { 165 return parseParZipInputStream(new ZipInputStream (ClassLoaderUtil.getStream(parResource))); 166 } 167 168 170 public List getNodes() { 172 return nodes; 173 } 174 175 public Map getNodesMap() { 177 if (nodesMap==null) { 178 nodesMap = new HashMap (); 179 if (nodes!=null) { 180 Iterator iter = nodes.iterator(); 181 while (iter.hasNext()) { 182 Node node = (Node) iter.next(); 183 nodesMap.put(node.getName(),node); 184 } 185 } 186 } 187 return nodesMap; 188 } 189 190 public Node getNode(String name) { 192 if (nodes==null) return null; 193 return (Node) getNodesMap().get(name); 194 } 195 196 public boolean hasNode(String name) { 198 if (nodes==null) return false; 199 return getNodesMap().containsKey(name); 200 } 201 202 public Node addNode(Node node) { 204 if (node == null) throw new IllegalArgumentException ("can't add a null node to a processdefinition"); 205 if (nodes == null) nodes = new ArrayList (); 206 nodes.add(node); 207 node.processDefinition = this; 208 nodesMap = null; 209 210 if(node instanceof StartState) { 211 this.startState = (StartState) node; 212 } 213 return node; 214 } 215 216 public Node removeNode(Node node) { 218 Node removedNode = null; 219 if (node == null) throw new IllegalArgumentException ("can't remove a null node from a process definition"); 220 if (nodes != null) { 221 if (nodes.remove(node)) { 222 removedNode = node; 223 removedNode.processDefinition = null; 224 nodesMap = null; 225 } 226 } 227 228 if (startState==removedNode) { 229 startState = null; 230 } 231 return removedNode; 232 } 233 234 public void reorderNode(int oldIndex, int newIndex) { 236 if ( (nodes!=null) 237 && (Math.min(oldIndex, newIndex)>=0) 238 && (Math.max(oldIndex, newIndex)<nodes.size()) ) { 239 Object o = nodes.remove(oldIndex); 240 nodes.add(newIndex, o); 241 } else { 242 throw new IndexOutOfBoundsException ("couldn't reorder element from index '"+oldIndex+"' to index '"+newIndex+"' in nodeList '"+nodes+"'"); 243 } 244 } 245 246 public String generateNodeName() { 248 return generateNodeName(nodes); 249 } 250 251 public Node findNode(String hierarchicalName) { 253 return findNode(this, hierarchicalName); 254 } 255 256 public static String generateNodeName(List nodes) { 257 String name = null; 258 if (nodes==null) { 259 name = "1"; 260 } else { 261 int n = 1; 262 while (containsName(nodes, Integer.toString(n))) n++; 263 name = Integer.toString(n); 264 } 265 return name; 266 } 267 268 private static boolean containsName(List nodes, String name) { 269 Iterator iter = nodes.iterator(); 270 while (iter.hasNext()) { 271 Node node = (Node) iter.next(); 272 if ( name.equals(node.getName()) ) { 273 return true; 274 } 275 } 276 return false; 277 } 278 279 public static Node findNode(NodeCollection nodeCollection, String hierarchicalName) { 280 Node node = null; 281 if ((hierarchicalName != null) && (!"".equals(hierarchicalName.trim())) ) { 282 283 if ( (hierarchicalName.startsWith("/")) 284 && (nodeCollection instanceof SuperState) ){ 285 nodeCollection = ((SuperState)nodeCollection).getProcessDefinition(); 286 } 287 288 StringTokenizer tokenizer = new StringTokenizer (hierarchicalName, "/"); 289 while (tokenizer.hasMoreElements()) { 290 String namePart = tokenizer.nextToken(); 291 if ("..".equals(namePart) ) { 292 if (nodeCollection instanceof ProcessDefinition) { 293 throw new RuntimeException ("couldn't find node '"+hierarchicalName+"' because of a '..' on the process definition."); 294 } 295 nodeCollection = (NodeCollection) ((GraphElement)nodeCollection).getParent(); 296 } else if ( tokenizer.hasMoreElements() ) { 297 nodeCollection = (NodeCollection)nodeCollection.getNode(namePart); 298 } else { 299 node = nodeCollection.getNode(namePart); 300 } 301 } 302 } 303 return node; 304 } 305 306 public void setStartState(StartState startState) { 307 if ( (this.startState!=startState) 308 && (this.startState!=null) ){ 309 removeNode(this.startState); 310 } 311 this.startState = startState; 312 if (startState!=null) { 313 addNode(startState); 314 } 315 } 316 317 public GraphElement getParent() { 318 return null; 319 } 320 321 323 327 public Action addAction(Action action) { 328 if (action == null) throw new IllegalArgumentException ("can't add a null action to an process definition"); 329 if (action.getName() == null) throw new IllegalArgumentException ("can't add an unnamed action to an process definition"); 330 if (actions == null) actions = new HashMap (); 331 actions.put(action.getName(), action); 332 action.processDefinition = this; 333 return action; 334 } 335 336 340 public void removeAction(Action action) { 341 if (action == null) throw new IllegalArgumentException ("can't remove a null action from an process definition"); 342 if (actions != null) { 343 if (! actions.containsValue(action)) { 344 throw new IllegalArgumentException ("can't remove an action that is not part of this process definition"); 345 } 346 actions.remove(action.getName()); 347 action.processDefinition = null; 348 } 349 } 350 351 public Action getAction(String name) { 352 if (actions == null) return null; 353 return (Action) actions.get(name); 354 } 355 356 public Map getActions() { 357 return actions; 358 } 359 360 public boolean hasActions() { 361 return ( (actions!=null) 362 && (actions.size()>0) ); 363 } 364 365 367 public Object createInstance() { 368 return new ProcessInstance(this); 369 } 370 371 public ModuleDefinition addDefinition(ModuleDefinition moduleDefinition) { 372 if (moduleDefinition == null) throw new IllegalArgumentException ("can't add a null moduleDefinition to a process definition"); 373 if (definitions == null) 374 definitions = new HashMap (); 375 definitions.put(moduleDefinition.getClass().getName(), moduleDefinition); 376 moduleDefinition.setProcessDefinition(this); 377 return moduleDefinition; 378 } 379 380 public ModuleDefinition removeDefinition(ModuleDefinition moduleDefinition) { 381 ModuleDefinition removedDefinition = null; 382 if (moduleDefinition == null) throw new IllegalArgumentException ("can't remove a null moduleDefinition from a process definition"); 383 if (definitions != null) { 384 removedDefinition = (ModuleDefinition) definitions.remove(moduleDefinition.getClass().getName()); 385 if (removedDefinition!=null) { 386 moduleDefinition.setProcessDefinition(null); 387 } 388 } 389 return removedDefinition; 390 } 391 392 public ModuleDefinition getDefinition(Class clazz) { 393 ModuleDefinition moduleDefinition = null; 394 if (definitions != null) { 395 moduleDefinition = (ModuleDefinition) definitions.get(clazz.getName()); 396 } 397 return moduleDefinition; 398 } 399 400 public ContextDefinition getContextDefinition() { 401 return (ContextDefinition) getDefinition(ContextDefinition.class); 402 } 403 404 public FileDefinition getFileDefinition() { 405 return (FileDefinition) getDefinition(FileDefinition.class); 406 } 407 412 public TaskMgmtDefinition getTaskMgmtDefinition() { 413 return (TaskMgmtDefinition) getDefinition(TaskMgmtDefinition.class); 414 } 415 416 public Map getDefinitions() { 417 return definitions; 418 } 419 420 public void setDefinitions(Map definitions) { 421 this.definitions = definitions; 422 } 423 424 426 public int getVersion() { 427 return version; 428 } 429 430 public void setVersion(int version) { 431 this.version = version; 432 } 433 434 public StartState getStartState() { 435 return startState; 436 } 437 438 public boolean isTerminationImplicit() { 439 return isTerminationImplicit; 440 } 441 442 public void setTerminationImplicit(boolean isTerminationImplicit) { 443 this.isTerminationImplicit = isTerminationImplicit; 444 } 445 } 446 | Popular Tags |