1 5 package com.opensymphony.workflow.loader; 6 7 import com.opensymphony.workflow.InvalidWorkflowDescriptorException; 8 import com.opensymphony.workflow.util.Validatable; 9 10 import org.w3c.dom.Element ; 11 import org.w3c.dom.Node ; 12 import org.w3c.dom.NodeList ; 13 14 import org.xml.sax.*; 15 16 import java.io.*; 17 18 import java.util.*; 19 20 import javax.xml.parsers.DocumentBuilder ; 21 import javax.xml.parsers.DocumentBuilderFactory ; 22 23 24 30 public class WorkflowDescriptor extends AbstractDescriptor implements Validatable { 31 33 public static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; 34 public static final String DOCTYPE_DECL = "<!DOCTYPE workflow PUBLIC \"-//OpenSymphony Group//DTD OSWorkflow 2.7//EN\" \"http://www.opensymphony.com/osworkflow/workflow_2_7.dtd\">"; 35 36 38 protected List commonActionsList = new ArrayList(); protected List globalActions = new ArrayList(); 40 protected List initialActions = new ArrayList(); 41 protected List joins = new ArrayList(); 42 protected List registers = new ArrayList(); 43 protected List splits = new ArrayList(); 44 protected List steps = new ArrayList(); 45 protected Map commonActions = new HashMap(); 46 protected Map metaAttributes = new HashMap(); 47 protected Map timerFunctions = new HashMap(); 48 49 51 public WorkflowDescriptor() { 52 } 53 54 public WorkflowDescriptor(Element root) { 55 init(root); 56 } 57 58 60 public ActionDescriptor getAction(int id) { 61 for (Iterator iterator = globalActions.iterator(); iterator.hasNext();) { 63 ActionDescriptor actionDescriptor = (ActionDescriptor) iterator.next(); 64 65 if (actionDescriptor.getId() == id) { 66 return actionDescriptor; 67 } 68 } 69 70 for (Iterator iterator = steps.iterator(); iterator.hasNext();) { 72 StepDescriptor stepDescriptor = (StepDescriptor) iterator.next(); 73 ActionDescriptor actionDescriptor = stepDescriptor.getAction(id); 74 75 if (actionDescriptor != null) { 76 return actionDescriptor; 77 } 78 } 79 80 return null; 81 } 82 83 87 public Map getCommonActions() { 88 return commonActions; 89 } 90 91 95 public List getGlobalActions() { 96 return globalActions; 97 } 98 99 public ActionDescriptor getInitialAction(int id) { 100 for (Iterator iterator = initialActions.iterator(); iterator.hasNext();) { 101 ActionDescriptor actionDescriptor = (ActionDescriptor) iterator.next(); 102 103 if (actionDescriptor.getId() == id) { 104 return actionDescriptor; 105 } 106 } 107 108 return null; 109 } 110 111 115 public List getInitialActions() { 116 return initialActions; 117 } 118 119 public JoinDescriptor getJoin(int id) { 120 for (Iterator iterator = joins.iterator(); iterator.hasNext();) { 121 JoinDescriptor joinDescriptor = (JoinDescriptor) iterator.next(); 122 123 if (joinDescriptor.getId() == id) { 124 return joinDescriptor; 125 } 126 } 127 128 return null; 129 } 130 131 135 public List getJoins() { 136 return joins; 137 } 138 139 public Map getMetaAttributes() { 140 return metaAttributes; 141 } 142 143 public List getRegisters() { 144 return registers; 145 } 146 147 public SplitDescriptor getSplit(int id) { 148 for (Iterator iterator = splits.iterator(); iterator.hasNext();) { 149 SplitDescriptor splitDescriptor = (SplitDescriptor) iterator.next(); 150 151 if (splitDescriptor.getId() == id) { 152 return splitDescriptor; 153 } 154 } 155 156 return null; 157 } 158 159 163 public List getSplits() { 164 return splits; 165 } 166 167 public StepDescriptor getStep(int id) { 168 for (Iterator iterator = steps.iterator(); iterator.hasNext();) { 169 StepDescriptor step = (StepDescriptor) iterator.next(); 170 171 if (step.getId() == id) { 172 return step; 173 } 174 } 175 176 return null; 177 } 178 179 183 public List getSteps() { 184 return steps; 185 } 186 187 193 public FunctionDescriptor setTriggerFunction(int id, FunctionDescriptor descriptor) { 194 return (FunctionDescriptor) timerFunctions.put(new Integer (id), descriptor); 195 } 196 197 public FunctionDescriptor getTriggerFunction(int id) { 198 return (FunctionDescriptor) this.timerFunctions.get(new Integer (id)); 199 } 200 201 205 public Map getTriggerFunctions() { 206 return timerFunctions; 207 } 208 209 214 public void addCommonAction(ActionDescriptor descriptor) { 215 addAction(commonActions, descriptor); 216 addAction(commonActionsList, descriptor); 217 } 218 219 224 public void addGlobalAction(ActionDescriptor descriptor) { 225 addAction(globalActions, descriptor); 226 } 227 228 233 public void addInitialAction(ActionDescriptor descriptor) { 234 addAction(initialActions, descriptor); 235 } 236 237 242 public void addJoin(JoinDescriptor descriptor) { 243 if (getJoin(descriptor.getId()) != null) { 244 throw new IllegalArgumentException ("Join with id " + descriptor.getId() + " already exists"); 245 } 246 247 joins.add(descriptor); 248 } 249 250 255 public void addSplit(SplitDescriptor descriptor) { 256 if (getSplit(descriptor.getId()) != null) { 257 throw new IllegalArgumentException ("Split with id " + descriptor.getId() + " already exists"); 258 } 259 260 splits.add(descriptor); 261 } 262 263 268 public void addStep(StepDescriptor descriptor) { 269 if (getStep(descriptor.getId()) != null) { 270 throw new IllegalArgumentException ("Step with id " + descriptor.getId() + " already exists"); 271 } 272 273 steps.add(descriptor); 274 } 275 276 283 public boolean removeAction(ActionDescriptor actionToRemove) { 284 for (Iterator iterator = getGlobalActions().iterator(); 286 iterator.hasNext();) { 287 ActionDescriptor actionDescriptor = (ActionDescriptor) iterator.next(); 288 289 if (actionDescriptor.getId() == actionToRemove.getId()) { 290 getGlobalActions().remove(actionDescriptor); 291 292 return true; 293 } 294 } 295 296 for (Iterator iterator = getSteps().iterator(); iterator.hasNext();) { 298 StepDescriptor stepDescriptor = (StepDescriptor) iterator.next(); 299 ActionDescriptor actionDescriptor = stepDescriptor.getAction(actionToRemove.getId()); 300 301 if (actionDescriptor != null) { 302 stepDescriptor.getActions().remove(actionDescriptor); 303 304 return true; 305 } 306 } 307 308 return false; 309 } 310 311 public void validate() throws InvalidWorkflowDescriptorException { 312 ValidationHelper.validate(this.getRegisters()); 313 ValidationHelper.validate(this.getTriggerFunctions().values()); 314 ValidationHelper.validate(this.getGlobalActions()); 315 ValidationHelper.validate(this.getInitialActions()); 316 ValidationHelper.validate(this.getCommonActions().values()); 317 ValidationHelper.validate(this.getSteps()); 318 ValidationHelper.validate(this.getSplits()); 319 ValidationHelper.validate(this.getJoins()); 320 321 Set actions = new HashSet(); 322 Iterator i = globalActions.iterator(); 323 324 while (i.hasNext()) { 325 ActionDescriptor action = (ActionDescriptor) i.next(); 326 actions.add(new Integer (action.getId())); 327 } 328 329 i = getSteps().iterator(); 330 331 while (i.hasNext()) { 332 StepDescriptor step = (StepDescriptor) i.next(); 333 Iterator j = step.getActions().iterator(); 334 335 while (j.hasNext()) { 336 ActionDescriptor action = (ActionDescriptor) j.next(); 337 338 if (!this.getCommonActions().containsKey(new Integer (action.getId()))) { 340 if (!actions.add(new Integer (action.getId()))) { 341 throw new InvalidWorkflowDescriptorException("Duplicate occurance of action ID " + action.getId() + " found in step " + step.getId()); 342 } 343 } 344 } 345 } 346 347 validateDTD(); 348 } 349 350 public void writeXML(PrintWriter out, int indent) { 351 XMLUtil.printIndent(out, indent++); 352 out.println("<workflow>"); 353 354 Iterator iter = metaAttributes.entrySet().iterator(); 355 356 while (iter.hasNext()) { 357 Map.Entry entry = (Map.Entry) iter.next(); 358 XMLUtil.printIndent(out, indent); 359 out.print("<meta name=\""); 360 out.print(entry.getKey()); 361 out.print("\">"); 362 out.print(entry.getValue()); 363 out.println("</meta>"); 364 } 365 366 if (registers.size() > 0) { 367 XMLUtil.printIndent(out, indent++); 368 out.println("<registers>"); 369 370 for (int i = 0; i < registers.size(); i++) { 371 RegisterDescriptor register = (RegisterDescriptor) registers.get(i); 372 register.writeXML(out, indent); 373 } 374 375 XMLUtil.printIndent(out, --indent); 376 out.println("</registers>"); 377 } 378 379 XMLUtil.printIndent(out, indent++); 380 out.println("<initial-actions>"); 381 382 for (int i = 0; i < initialActions.size(); i++) { 383 ActionDescriptor action = (ActionDescriptor) initialActions.get(i); 384 action.writeXML(out, indent); 385 } 386 387 XMLUtil.printIndent(out, --indent); 388 out.println("</initial-actions>"); 389 390 if (globalActions.size() > 0) { 391 XMLUtil.printIndent(out, indent++); 392 out.println("<global-actions>"); 393 394 for (int i = 0; i < globalActions.size(); i++) { 395 ActionDescriptor action = (ActionDescriptor) globalActions.get(i); 396 action.writeXML(out, indent); 397 } 398 399 XMLUtil.printIndent(out, --indent); 400 out.println("</global-actions>"); 401 } 402 403 if (commonActions.size() > 0) { 404 XMLUtil.printIndent(out, indent++); 405 out.println("<common-actions>"); 406 407 Iterator commonActionsItr = getCommonActions().values().iterator(); 408 409 while (commonActionsItr.hasNext()) { 410 ActionDescriptor action = (ActionDescriptor) commonActionsItr.next(); 411 action.writeXML(out, indent); 412 } 413 414 XMLUtil.printIndent(out, --indent); 415 out.println("</common-actions>"); 416 } 417 418 XMLUtil.printIndent(out, indent++); 419 out.println("<steps>"); 420 421 for (int i = 0; i < steps.size(); i++) { 422 StepDescriptor step = (StepDescriptor) steps.get(i); 423 step.writeXML(out, indent); 424 } 425 426 XMLUtil.printIndent(out, --indent); 427 out.println("</steps>"); 428 429 if (splits.size() > 0) { 430 XMLUtil.printIndent(out, indent++); 431 out.println("<splits>"); 432 433 for (int i = 0; i < splits.size(); i++) { 434 SplitDescriptor split = (SplitDescriptor) splits.get(i); 435 split.writeXML(out, indent); 436 } 437 438 XMLUtil.printIndent(out, --indent); 439 out.println("</splits>"); 440 } 441 442 if (joins.size() > 0) { 443 XMLUtil.printIndent(out, indent++); 444 out.println("<joins>"); 445 446 for (int i = 0; i < joins.size(); i++) { 447 JoinDescriptor join = (JoinDescriptor) joins.get(i); 448 join.writeXML(out, indent); 449 } 450 451 XMLUtil.printIndent(out, --indent); 452 out.println("</joins>"); 453 } 454 455 XMLUtil.printIndent(out, --indent); 456 out.println("</workflow>"); 457 } 458 459 protected void init(Element root) { 460 NodeList children = root.getChildNodes(); 461 462 for (int i = 0; i < children.getLength(); i++) { 463 Node child = (Node ) children.item(i); 464 465 if (child.getNodeName().equals("meta")) { 466 Element meta = (Element ) child; 467 String value = XMLUtil.getText(meta); 468 this.metaAttributes.put(meta.getAttribute("name"), value); 469 } 470 } 471 472 Element r = XMLUtil.getChildElement(root, "registers"); 474 475 if (r != null) { 476 List registers = XMLUtil.getChildElements(r, "register"); 477 478 for (int i = 0; i < registers.size(); i++) { 479 Element register = (Element ) registers.get(i); 480 RegisterDescriptor registerDescriptor = new RegisterDescriptor(register); 481 registerDescriptor.setParent(this); 482 this.registers.add(registerDescriptor); 483 } 484 } 485 486 Element intialActionsElement = XMLUtil.getChildElement(root, "initial-actions"); 488 List initialActions = XMLUtil.getChildElements(intialActionsElement, "action"); 489 490 for (int i = 0; i < initialActions.size(); i++) { 491 Element initialAction = (Element ) initialActions.get(i); 492 ActionDescriptor actionDescriptor = new ActionDescriptor(initialAction); 493 actionDescriptor.setParent(this); 494 this.initialActions.add(actionDescriptor); 495 } 496 497 Element globalActionsElement = XMLUtil.getChildElement(root, "global-actions"); 499 500 if (globalActionsElement != null) { 501 List globalActions = XMLUtil.getChildElements(globalActionsElement, "action"); 502 503 for (int i = 0; i < globalActions.size(); i++) { 504 Element globalAction = (Element ) globalActions.get(i); 505 ActionDescriptor actionDescriptor = new ActionDescriptor(globalAction); 506 actionDescriptor.setParent(this); 507 this.globalActions.add(actionDescriptor); 508 } 509 } 510 511 Element commonActionsElement = XMLUtil.getChildElement(root, "common-actions"); 515 516 if (commonActionsElement != null) { 517 List commonActions = XMLUtil.getChildElements(commonActionsElement, "action"); 518 519 for (int i = 0; i < commonActions.size(); i++) { 520 Element commonAction = (Element ) commonActions.get(i); 521 ActionDescriptor actionDescriptor = new ActionDescriptor(commonAction); 522 actionDescriptor.setParent(this); 523 addCommonAction(actionDescriptor); 524 } 525 } 526 527 Element timerFunctionsElement = XMLUtil.getChildElement(root, "trigger-functions"); 529 530 if (timerFunctionsElement != null) { 531 List timerFunctions = XMLUtil.getChildElements(timerFunctionsElement, "trigger-function"); 532 533 for (int i = 0; i < timerFunctions.size(); i++) { 534 Element timerFunction = (Element ) timerFunctions.get(i); 535 Integer id = new Integer (timerFunction.getAttribute("id")); 536 FunctionDescriptor function = new FunctionDescriptor(XMLUtil.getChildElement(timerFunction, "function")); 537 function.setParent(this); 538 this.timerFunctions.put(id, function); 539 } 540 } 541 542 Element stepsElement = XMLUtil.getChildElement(root, "steps"); 544 List steps = XMLUtil.getChildElements(stepsElement, "step"); 545 546 for (int i = 0; i < steps.size(); i++) { 547 Element step = (Element ) steps.get(i); 548 StepDescriptor stepDescriptor = new StepDescriptor(step, this); 549 this.steps.add(stepDescriptor); 550 } 551 552 Element splitsElement = XMLUtil.getChildElement(root, "splits"); 554 555 if (splitsElement != null) { 556 List split = XMLUtil.getChildElements(splitsElement, "split"); 557 558 for (int i = 0; i < split.size(); i++) { 559 Element s = (Element ) split.get(i); 560 SplitDescriptor splitDescriptor = new SplitDescriptor(s); 561 splitDescriptor.setParent(this); 562 this.splits.add(splitDescriptor); 563 } 564 } 565 566 Element joinsElement = XMLUtil.getChildElement(root, "joins"); 568 569 if (joinsElement != null) { 570 List join = XMLUtil.getChildElements(joinsElement, "join"); 571 572 for (int i = 0; i < join.size(); i++) { 573 Element s = (Element ) join.get(i); 574 JoinDescriptor joinDescriptor = new JoinDescriptor(s); 575 joinDescriptor.setParent(this); 576 this.joins.add(joinDescriptor); 577 } 578 } 579 } 580 581 private void addAction(Object actionsCollectionOrMap, ActionDescriptor descriptor) { 583 if (getAction(descriptor.getId()) != null) { 584 throw new IllegalArgumentException ("action with id " + descriptor.getId() + " already exists for this step."); 585 } 586 587 if (actionsCollectionOrMap instanceof Map) { 588 ((Map) actionsCollectionOrMap).put(new Integer (descriptor.getId()), descriptor); 589 } else { 590 ((Collection) actionsCollectionOrMap).add(descriptor); 591 } 592 } 593 594 private void validateDTD() throws InvalidWorkflowDescriptorException { 595 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 596 dbf.setNamespaceAware(true); 597 dbf.setValidating(true); 598 599 StringWriter sw = new StringWriter(); 600 PrintWriter writer = new PrintWriter(sw); 601 writer.println(XML_HEADER); 602 writer.println(DOCTYPE_DECL); 603 writeXML(writer, 0); 604 605 try { 606 DocumentBuilder db = dbf.newDocumentBuilder(); 607 db.setEntityResolver(new DTDEntityResolver()); 608 609 WorkflowLoader.AllExceptionsErrorHandler errorHandler = new WorkflowLoader.AllExceptionsErrorHandler(); 610 db.setErrorHandler(errorHandler); 611 db.parse(new InputSource(new StringReader(sw.toString()))); 612 613 if (errorHandler.getExceptions().size() > 0) { 614 throw new InvalidWorkflowDescriptorException(errorHandler.getExceptions().toString()); 615 } 616 } catch (InvalidWorkflowDescriptorException e) { 617 throw e; 618 } catch (Exception e) { 619 throw new InvalidWorkflowDescriptorException(e.toString()); 620 } 621 } 622 } 623 | Popular Tags |