001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Florent Guillaume 016 */ 017package org.nuxeo.ecm.platform.routing.core.impl; 018 019import java.io.Serializable; 020import java.util.ArrayList; 021import java.util.Calendar; 022import java.util.Date; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.commons.lang.BooleanUtils; 027import org.apache.commons.lang.builder.ToStringBuilder; 028import org.nuxeo.ecm.core.api.CoreSession; 029import org.nuxeo.ecm.core.api.DocumentModel; 030import org.nuxeo.ecm.core.api.model.Property; 031import org.nuxeo.ecm.core.api.model.impl.ListProperty; 032import org.nuxeo.ecm.core.api.model.impl.MapProperty; 033import org.nuxeo.ecm.platform.routing.api.DocumentRoute; 034import org.nuxeo.ecm.platform.routing.api.exception.DocumentRouteException; 035 036/** 037 * A node for a route graph. Represents operation chains, associated task and form, output transitions and their 038 * conditions, etc. 039 * 040 * @since 5.6 041 */ 042public interface GraphNode { 043 044 String MERGE_ONE = "one"; 045 046 String MERGE_ALL = "all"; 047 048 String PROP_NODE_ID = "rnode:nodeId"; 049 050 String PROP_TITLE = "dc:title"; 051 052 String PROP_START = "rnode:start"; 053 054 String PROP_STOP = "rnode:stop"; 055 056 String PROP_MERGE = "rnode:merge"; 057 058 String PROP_COUNT = "rnode:count"; 059 060 String PROP_CANCELED = "rnode:canceled"; 061 062 String PROP_INPUT_CHAIN = "rnode:inputChain"; 063 064 String PROP_OUTPUT_CHAIN = "rnode:outputChain"; 065 066 String PROP_HAS_TASK = "rnode:hasTask"; 067 068 String PROP_VARIABLES_FACET = "rnode:variablesFacet"; 069 070 String PROP_TRANSITIONS = "rnode:transitions"; 071 072 String PROP_TRANS_NAME = "name"; 073 074 String PROP_TRANS_TARGET = "targetId"; 075 076 String PROP_TRANS_CONDITION = "condition"; 077 078 String PROP_TRANS_RESULT = "result"; 079 080 String PROP_TRANS_CHAIN = "chain"; 081 082 String PROP_TRANS_LABEL = "label"; 083 084 /** 085 * @since 7.1 a transition can hold a custom path 086 */ 087 String PROP_TRANS_PATH = "path"; 088 089 String PROP_TASK_ASSIGNEES = "rnode:taskAssignees"; 090 091 String PROP_TASK_ASSIGNEES_VAR = "rnode:taskAssigneesExpr"; 092 093 String PROP_TASK_ASSIGNEES_PERMISSION = "rnode:taskAssigneesPermission"; 094 095 String PROP_TASK_DUE_DATE = "rnode:taskDueDate"; 096 097 String PROP_TASK_DIRECTIVE = "rnode:taskDirective"; 098 099 String PROP_TASK_LAYOUT = "rnode:taskLayout"; 100 101 String PROP_TASK_BUTTONS = "rnode:taskButtons"; 102 103 String PROP_BTN_NAME = "name"; 104 105 String PROP_BTN_LABEL = "label"; 106 107 String PROP_BTN_FILTER = "filter"; 108 109 String PROP_NODE_X_COORDINATE = "rnode:taskX"; 110 111 String PROP_NODE_Y_COORDINATE = "rnode:taskY"; 112 113 /** 114 * @since 5.7.3 a node can create multiple tasks, in this case, this stores the status of the last task ended 115 */ 116 String PROP_NODE_BUTTON = "rnode:button"; 117 118 String PROP_NODE_START_DATE = "rnode:startDate"; 119 120 String PROP_NODE_END_DATE = "rnode:endDate"; 121 122 String PROP_NODE_LAST_ACTOR = "rnode:lastActor"; 123 124 String PROP_TASK_DOC_TYPE = "rnode:taskDocType"; 125 126 String PROP_TASK_NOTIFICATION_TEMPLATE = "rnode:taskNotificationTemplate"; 127 128 String PROP_TASK_DUE_DATE_EXPR = "rnode:taskDueDateExpr"; 129 130 /** @since 5.7.2 */ 131 String PROP_EXECUTE_ONLY_FIRST_TRANSITION = "rnode:executeOnlyFirstTransition"; 132 133 /** 134 * The sub-route model id (expression) to run, if present. 135 * 136 * @since 5.7.2 137 */ 138 String PROP_SUB_ROUTE_MODEL_EXPR = "rnode:subRouteModelExpr"; 139 140 /** 141 * The sub-route instance id being run while this node is suspended. 142 * 143 * @since 5.7.2 144 */ 145 String PROP_SUB_ROUTE_INSTANCE_ID = "rnode:subRouteInstanceId"; 146 147 /** 148 * The sub-route variables to set (key/value list). 149 * 150 * @since 5.7.2 151 */ 152 String PROP_SUB_ROUTE_VARS = "rnode:subRouteVariables"; 153 154 /** @since 5.7.2 */ 155 String PROP_KEYVALUE_KEY = "key"; 156 157 /** @since 5.7.2 */ 158 String PROP_KEYVALUE_VALUE = "value"; 159 160 // @since 5.7.2 161 String PROP_ESCALATION_RULES = "rnode:escalationRules"; 162 163 // @since 5.7.2 164 String PROP_ESCALATION_RULE_ID = "name"; 165 166 // @since 5.7.2 167 String PROP_ESCALATION_RULE_LABEL = "label"; 168 169 // @since 5.7.2 170 String PROP_ESCALATION_RULE_MULTIPLE_EXECUTION = "multipleExecution"; 171 172 // @since 5.7.2 173 String PROP_ESCALATION_RULE_CONDITION = "condition"; 174 175 // @since 5.7.2 176 String PROP_ESCALATION_RULE_CHAIN = "chain"; 177 178 // @since 5.7.2 179 String PROP_ESCALATION_RULE_EXECUTED = "executed"; 180 181 // @since 5.9.3 182 String PROP_LAST_EXECUTION_TIME = "executionDate"; 183 184 // @since 5.7.3 185 String PROP_HAS_MULTIPLE_TASKS = "rnode:hasMultipleTasks"; 186 187 // @since 5.7.3 188 String PROP_TASKS_INFO = "rnode:tasksInfo"; 189 190 // @since 5.7.3 191 String PROP_TASK_INFO_ACTOR = "actor"; 192 193 // @since 5.7.3 194 String PROP_TASK_INFO_COMMENT = "comment"; 195 196 // @since 5.7.3 197 String PROP_TASK_INFO_STATUS = "status"; 198 199 // @since 5.7.3 200 String PROP_TASK_INFO_ENDED = "ended"; 201 202 // @since 5.7.3 203 String PROP_TASK_INFO_TASK_DOC_ID = "taskDocId"; 204 205 // @since 5.7.3 206 String PROP_ALLOW_TASK_REASSIGNMENT = "rnode:allowTaskReassignment"; 207 208 // @since 5.6 209 // if present as the node variable, acts as a built-in variable: 210 // is passed to the task comment and logged in by audit; 211 // internally rested when set on node having multiple tasks. 212 String NODE_VARIABLE_COMMENT = "comment"; 213 214 /** 215 * The internal state of a node. 216 */ 217 enum State { 218 /** Node is ready. */ 219 READY("ready", "toReady"), 220 /** Merge node is waiting for more incoming transitions. */ 221 WAITING("waiting", "toWaiting"), 222 /** While executing input phase. Not persisted. */ 223 RUNNING_INPUT, 224 /** Task node is waiting for task to be done. */ 225 SUSPENDED("suspended", "toSuspended"), 226 /** While executing output phase. Not persisted. */ 227 RUNNING_OUTPUT; 228 229 private final String lifeCycleState; 230 231 private final String transition; 232 233 private State() { 234 lifeCycleState = null; 235 transition = null; 236 } 237 238 private State(String lifeCycleState, String transition) { 239 this.lifeCycleState = lifeCycleState; 240 this.transition = transition; 241 } 242 243 /** 244 * Corresponding lifecycle state. 245 */ 246 public String getLifeCycleState() { 247 return lifeCycleState; 248 } 249 250 /** 251 * Transition leading to this state. 252 */ 253 public String getTransition() { 254 return transition; 255 } 256 257 public static State fromString(String s) { 258 try { 259 return State.valueOf(s.toUpperCase()); 260 } catch (IllegalArgumentException e) { 261 throw new IllegalArgumentException(s); 262 } 263 } 264 } 265 266 /** 267 * @since 7.1 268 */ 269 class Point { 270 271 public double x; 272 273 public double y; 274 275 public Point(double x, double y) { 276 this.x = x; 277 this.y = y; 278 } 279 } 280 281 class Transition implements Comparable<Transition>, Serializable { 282 283 public GraphNode source; 284 285 public MapProperty prop; 286 287 public String id; 288 289 public String condition; 290 291 public String chain; 292 293 public String target; 294 295 public String label; 296 297 public boolean result; 298 299 /** 300 * @since 7.1 301 */ 302 public List<Point> path; 303 304 /** Computed by graph. */ 305 public boolean loop; 306 307 protected Transition(GraphNode source, Property p) { 308 this.source = source; 309 prop = (MapProperty) p; 310 id = (String) prop.get(PROP_TRANS_NAME).getValue(); 311 condition = (String) prop.get(PROP_TRANS_CONDITION).getValue(); 312 chain = (String) prop.get(PROP_TRANS_CHAIN).getValue(); 313 target = (String) prop.get(PROP_TRANS_TARGET).getValue(); 314 label = (String) prop.get(PROP_TRANS_LABEL).getValue(); 315 Property resultProp = prop.get(PROP_TRANS_RESULT); 316 if (resultProp != null) { 317 result = BooleanUtils.isTrue(resultProp.getValue(Boolean.class)); 318 } 319 } 320 321 protected void setResult(boolean bool) { 322 result = bool; 323 prop.get(PROP_TRANS_RESULT).setValue(Boolean.valueOf(bool)); 324 } 325 326 @Override 327 public int compareTo(Transition other) { 328 return id.compareTo(other.id); 329 } 330 331 @Override 332 public String toString() { 333 return new ToStringBuilder(this).append("id", id).append("condition", condition).append("result", result).toString(); 334 } 335 336 public String getTarget() { 337 return target; 338 } 339 340 public String getId() { 341 return id; 342 } 343 344 public String getLabel() { 345 return label; 346 } 347 348 /** 349 * @since 7.1 350 */ 351 public List<Point> getPath() { 352 if (path == null) { 353 path = computePath(); 354 } 355 return path; 356 } 357 358 protected List<Point> computePath() { 359 ListProperty props = (ListProperty) prop.get(PROP_TRANS_PATH); 360 List<Point> points = new ArrayList<>(props.size()); 361 for (Property p : props) { 362 points.add(new Point( 363 (Double) p.get("x").getValue(), 364 (Double) p.get("y").getValue())); 365 } 366 return points; 367 } 368 } 369 370 public class Button implements Comparable<Button> { 371 372 public GraphNode source; 373 374 public String name; 375 376 public String label; 377 378 public String filter; 379 380 public MapProperty prop; 381 382 public Button(GraphNode source, Property p) { 383 this.source = source; 384 this.prop = (MapProperty) p; 385 name = (String) prop.get(PROP_BTN_NAME).getValue(); 386 label = (String) prop.get(PROP_BTN_LABEL).getValue(); 387 filter = (String) prop.get(PROP_BTN_FILTER).getValue(); 388 } 389 390 @Override 391 public int compareTo(Button other) { 392 return name.compareTo(other.name); 393 } 394 395 public String getLabel() { 396 return label; 397 } 398 399 public String getName() { 400 return name; 401 } 402 403 public String getFilter() { 404 return filter; 405 } 406 } 407 408 /** 409 * @since 5.7.2 410 */ 411 class EscalationRule implements Comparable<EscalationRule> { 412 413 protected String id; 414 415 protected String label; 416 417 protected boolean multipleExecution; 418 419 protected String condition; 420 421 protected boolean executed; 422 423 protected String chain; 424 425 protected MapProperty prop; 426 427 protected GraphNode node; 428 429 /** 430 * @since 5.9.3 431 */ 432 protected Calendar lastExcutionTime; 433 434 public EscalationRule(GraphNode node, Property p) { 435 this.prop = (MapProperty) p; 436 this.node = node; 437 this.id = (String) p.get(PROP_ESCALATION_RULE_ID).getValue(); 438 this.label = (String) p.get(PROP_ESCALATION_RULE_LABEL).getValue(); 439 Property multipleEvaluationProp = prop.get(PROP_ESCALATION_RULE_MULTIPLE_EXECUTION); 440 if (multipleEvaluationProp != null) { 441 multipleExecution = BooleanUtils.isTrue(multipleEvaluationProp.getValue(Boolean.class)); 442 } 443 this.condition = (String) p.get(PROP_ESCALATION_RULE_CONDITION).getValue(); 444 Property evaluatedProp = prop.get(PROP_ESCALATION_RULE_EXECUTED); 445 if (evaluatedProp != null) { 446 executed = BooleanUtils.isTrue(evaluatedProp.getValue(Boolean.class)); 447 } 448 this.chain = (String) p.get(PROP_ESCALATION_RULE_CHAIN).getValue(); 449 this.lastExcutionTime = (Calendar) p.get(PROP_LAST_EXECUTION_TIME).getValue(); 450 } 451 452 @Override 453 public int compareTo(EscalationRule o) { 454 return id.compareTo(o.id); 455 } 456 457 public String getLabel() { 458 return label; 459 } 460 461 public String getChain() { 462 return chain; 463 } 464 465 public GraphNode getNode() { 466 return node; 467 } 468 469 public void setExecuted(boolean executed) { 470 this.executed = executed; 471 prop.get(PROP_ESCALATION_RULE_EXECUTED).setValue(Boolean.valueOf(executed)); 472 if (executed) { 473 setExecutionTime(Calendar.getInstance()); 474 } 475 } 476 477 protected void setExecutionTime(Calendar time) { 478 prop.get(PROP_LAST_EXECUTION_TIME).setValue(time); 479 this.lastExcutionTime = time; 480 } 481 482 public boolean isExecuted() { 483 return executed; 484 } 485 486 public String getId() { 487 return id; 488 } 489 490 public boolean isMultipleExecution() { 491 return multipleExecution; 492 } 493 494 /** 495 * @since 5.9.3 Returns 'null' if the node was not executed, or the executed date was not computed ( for rules 496 * created before 497 * @5.9.3) 498 */ 499 public Calendar getLastExecutionTime() { 500 if (executed && lastExcutionTime != null) { 501 return lastExcutionTime; 502 } 503 return null; 504 } 505 } 506 507 /** 508 * @since 5.7.3 509 */ 510 class TaskInfo implements Comparable<TaskInfo>, Serializable { 511 512 protected String taskDocId; 513 514 protected String actor; 515 516 protected String comment; 517 518 protected String status; 519 520 protected boolean ended; 521 522 protected MapProperty prop; 523 524 protected GraphNode node; 525 526 public TaskInfo(GraphNode node, Property p) { 527 this.prop = (MapProperty) p; 528 this.node = node; 529 this.taskDocId = (String) p.get(PROP_TASK_INFO_TASK_DOC_ID).getValue(); 530 this.status = (String) p.get(PROP_TASK_INFO_STATUS).getValue(); 531 this.actor = (String) p.get(PROP_TASK_INFO_ACTOR).getValue(); 532 this.comment = (String) p.get(PROP_TASK_INFO_COMMENT).getValue(); 533 Property ended = prop.get(PROP_TASK_INFO_ENDED); 534 if (ended != null) { 535 this.ended = BooleanUtils.isTrue(ended.getValue(Boolean.class)); 536 } 537 } 538 539 public TaskInfo(GraphNode node, String taskDocId) { 540 this.node = node; 541 this.prop = (MapProperty) ((ListProperty) node.getDocument().getProperty(PROP_TASKS_INFO)).addEmpty(); 542 this.prop.get(PROP_TASK_INFO_TASK_DOC_ID).setValue(taskDocId); 543 this.taskDocId = taskDocId; 544 } 545 546 @Override 547 public int compareTo(TaskInfo o) { 548 return taskDocId.compareTo(o.taskDocId); 549 } 550 551 public String getTaskDocId() { 552 return taskDocId; 553 } 554 555 public String getActor() { 556 return actor; 557 } 558 559 public String getComment() { 560 return comment; 561 } 562 563 public String getStatus() { 564 return status; 565 } 566 567 public GraphNode getNode() { 568 return node; 569 } 570 571 public boolean isEnded() { 572 return ended; 573 } 574 575 public void setComment(String comment) { 576 this.comment = comment; 577 prop.get(PROP_TASK_INFO_COMMENT).setValue(comment); 578 } 579 580 public void setStatus(String status) { 581 this.status = status; 582 prop.get(PROP_TASK_INFO_STATUS).setValue(status); 583 584 } 585 586 public void setActor(String actor) { 587 this.actor = actor; 588 prop.get(PROP_TASK_INFO_ACTOR).setValue(actor); 589 } 590 591 public void setEnded(boolean ended) { 592 this.ended = ended; 593 prop.get(PROP_TASK_INFO_ENDED).setValue(Boolean.valueOf(ended)); 594 } 595 } 596 597 /** 598 * Get the node id. 599 * 600 * @return the node id 601 */ 602 String getId(); 603 604 /** 605 * Get the node state. 606 * 607 * @return the node state 608 */ 609 State getState(); 610 611 /** 612 * Set the node state. 613 * 614 * @param state the node state 615 */ 616 void setState(State state); 617 618 /** 619 * Checks if this is the start node. 620 */ 621 boolean isStart(); 622 623 /** 624 * Checks if this is a stop node. 625 */ 626 boolean isStop(); 627 628 /** 629 * Checks if this is a merge node. 630 */ 631 boolean isMerge(); 632 633 /** 634 * Checks if the merge is ready to execute (enough input transitions are present). 635 */ 636 boolean canMerge(); 637 638 /** 639 * Notes that this node was canceled (increments canceled counter). 640 */ 641 void setCanceled(); 642 643 /** 644 * Gets the canceled count for this node. 645 * 646 * @return 647 */ 648 long getCanceledCount(); 649 650 /** 651 * Cancels the tasks not ended on this node. 652 */ 653 void cancelTasks(); 654 655 /** 656 * Get input chain. 657 * 658 * @return the input chain 659 */ 660 String getInputChain(); 661 662 /** 663 * Get output chain. 664 * 665 * @return the output chain 666 */ 667 String getOutputChain(); 668 669 /** 670 * Checks it this node has an associated user task. 671 */ 672 boolean hasTask(); 673 674 /** 675 * Gets the task assignees 676 * 677 * @return the task assignees 678 */ 679 List<String> getTaskAssignees(); 680 681 /** 682 * Gets the due date 683 * 684 * @return 685 */ 686 Date getTaskDueDate(); 687 688 /** 689 * Gets the task directive 690 * 691 * @return 692 */ 693 String getTaskDirective(); 694 695 /** 696 * Gets the permission to the granted to the actors on this task on the document following the workflow 697 * 698 * @return 699 */ 700 String getTaskAssigneesPermission(); 701 702 /** 703 * Gets the task layout 704 * 705 * @return 706 */ 707 String getTaskLayout(); 708 709 /** 710 * @returns the taskDocType. If none is specified, the default task type is returned. 711 */ 712 String getTaskDocType(); 713 714 String getTaskNotificationTemplate(); 715 716 /** 717 * Does bookkeeping at node start. 718 */ 719 void starting(); 720 721 /** 722 * Does bookkeeping at node end. 723 */ 724 void ending(); 725 726 /** 727 * Executes an Automation chain in the context of this node. 728 * 729 * @param chainId the chain 730 */ 731 void executeChain(String chainId) throws DocumentRouteException; 732 733 /** Internal during graph init. */ 734 void initAddInputTransition(Transition transition); 735 736 /** 737 * Gets the input transitions. 738 */ 739 List<Transition> getInputTransitions(); 740 741 /** 742 * Gets the output transitions. 743 */ 744 List<Transition> getOutputTransitions(); 745 746 String getTaskDueDateExpr(); 747 748 /** 749 * Executes an Automation chain in the context of this node for a given transition 750 * 751 * @param transition the transition 752 */ 753 void executeTransitionChain(Transition transition) throws DocumentRouteException; 754 755 /** 756 * Evaluates transition conditions and returns the transitions that were true. 757 * <p> 758 * Transitions are evaluated in the order set on the node when the workflow was designed. Since @5.7.2 if the node 759 * has the property "executeOnlyFirstTransition" set to true, only the first transition evaluated to true is 760 * returned 761 * 762 * @return the true transitions 763 */ 764 List<Transition> evaluateTransitions() throws DocumentRouteException; 765 766 /** 767 * Sets the graph and node variables. 768 * 769 * @param map the map of variables 770 */ 771 void setAllVariables(Map<String, Object> map); 772 773 /** 774 * Sets the graph and node variables. 775 * 776 * @param map the map of variables 777 * @param allowGlobalVariablesAssignement if set to false, throw a DocumentRouteException when trying to set global 778 * variables when not supposed to 779 * @since 7.2 780 */ 781 void setAllVariables(Map<String, Object> map, final boolean allowGlobalVariablesAssignement); 782 783 /** 784 * Gets the task buttons 785 */ 786 List<Button> getTaskButtons(); 787 788 /** 789 * Has the node the given action. 790 * 791 * @since 7.2 792 */ 793 boolean hasTaskButton(final String name); 794 795 /** 796 * Gets the document representing this node 797 * 798 * @return 799 */ 800 DocumentModel getDocument(); 801 802 /** 803 * Gets a map containing the variables currently defined on this node 804 * 805 * @return 806 */ 807 Map<String, Serializable> getVariables(); 808 809 /** 810 * Gets a map containing the Json formatted variables currently defined on this node 811 * 812 * @return 813 * @since 7.2 814 */ 815 Map<String, Serializable> getJsonVariables(); 816 817 /** 818 * Sets the property button on the node, keeping the id of the last action executed by the user on the associated 819 * task if any 820 * 821 * @param status 822 */ 823 void setButton(String status); 824 825 /** 826 * Sets the last actor on a node (user who completed the task). 827 * 828 * @param actor the user id 829 */ 830 void setLastActor(String actor); 831 832 /** 833 * Evaluates the task assignees from the taskAssigneesVar 834 * <p> 835 * 836 * @return 837 */ 838 List<String> evaluateTaskAssignees() throws DocumentRouteException; 839 840 /** 841 * Evaluates the task due date from the taskDueDateExpr and sets it as the dueDate 842 * 843 * @return 844 * @throws DocumentRouteException 845 */ 846 Date computeTaskDueDate() throws DocumentRouteException; 847 848 /** 849 * Gets a map containing the workflow and node variables and workflow documents. 850 * 851 * @param detached The documents added into this map can be detached or not 852 */ 853 Map<String, Serializable> getWorkflowContextualInfo(CoreSession session, boolean detached); 854 855 /** 856 * When workflow engine runs an exclusive node, it evaluates the transition one by one and stops a soon as one of 857 * the transition is evaluated to true 858 * 859 * @since 5.7.2 860 */ 861 boolean executeOnlyFirstTransition(); 862 863 /** 864 * Checks if this node has a sub-route model defined. 865 * 866 * @return {@code true} if there is a sub-route 867 * @since 5.7.2 868 */ 869 boolean hasSubRoute() throws DocumentRouteException; 870 871 /** 872 * Gets the sub-route model id. 873 * <p> 874 * If this is present, then this node will be suspended while the sub-route is run. When the sub-route ends, this 875 * node will resume. 876 * 877 * @return the sub-route id, or {@code null} if none is defined 878 * @since 5.7.2 879 */ 880 String getSubRouteModelId() throws DocumentRouteException; 881 882 /** 883 * Starts the sub-route on this node. 884 * 885 * @return the sub-route 886 * @since 5.7.2 887 */ 888 DocumentRoute startSubRoute() throws DocumentRouteException; 889 890 /** 891 * Cancels the sub-route if there is one. 892 * 893 * @since 5.7.2 894 */ 895 void cancelSubRoute() throws DocumentRouteException; 896 897 /** 898 * Evaluates the rules for the escalation rules and returns the ones to be executed. The rules already executed and 899 * not having the property multipleExecution = true are also ignored 900 * 901 * @since 5.7.2 902 */ 903 List<EscalationRule> evaluateEscalationRules(); 904 905 /** 906 * Gets the list of all escalation rules for the node 907 * 908 * @since 5.7.2 909 */ 910 List<EscalationRule> getEscalationRules(); 911 912 /** 913 * Checks if this node has created multiple tasks, one for each assignees. 914 * 915 * @since 5.7.3 916 */ 917 boolean hasMultipleTasks(); 918 919 /** 920 * Gets all the tasks info for the tasks created from this node 921 * 922 * @since 5.7.3 923 */ 924 List<TaskInfo> getTasksInfo(); 925 926 /** 927 * Persist the info when a new task is created from this node 928 * 929 * @since 5.7.3 930 */ 931 void addTaskInfo(String taskId); 932 933 /** 934 * Persist these info from the task on the node. Status is the id of the button clicked to end the task by the 935 * actor. 936 * 937 * @since 5.7.3 938 */ 939 void updateTaskInfo(String taskId, boolean ended, String status, String actor, String comment); 940 941 /** 942 * Gets all the ended tasks originating from this node. This also counts the canceled tasks. 943 * 944 * @since 5.7.3 945 */ 946 List<TaskInfo> getEndedTasksInfo(); 947 948 /** 949 * Gets all the ended tasks originating from this node that were processed with a status. Doesn't count the canceled 950 * tasks. 951 * 952 * @since 5.7.3 953 */ 954 List<TaskInfo> getProcessedTasksInfo(); 955 956 /** 957 * Returns false if all tasks created from this node were ended. 958 * 959 * @since 5.7.3 960 */ 961 boolean hasOpenTasks(); 962 963 /** 964 * Returns true if tasks created from this node can be reassigned. 965 * 966 * @since 5.7.3 967 */ 968 boolean allowTaskReassignment(); 969 970 /** 971 * Sets the variable on this node if it exists as a Node Variable. 972 * 973 * @since 5.8 974 */ 975 public void setVariable(String name, String value); 976 977 /** 978 * Sets the node variables. 979 * 980 * @since 5.9.3, 5.8.0-HF11 981 * @param map the map of variables 982 */ 983 void setVariables(Map<String, Serializable> map); 984 985 /** 986 * Sets the variables of the workflow based on their JSON representation (especially for scalar lists). Eg. 987 * Map<String, String> map = new HashMap<String, String>(); 988 * map.put("contributors","[\"John Doe\", \"John Smith\"]"); map.put("title","Test Title"); 989 * 990 * @param map the map of variables 991 * @since 5.9.3, 5.8.0-HF11 992 */ 993 void setJSONVariables(Map<String, String> map); 994 995 /** 996 * @since 7.4 997 */ 998 void removeTaskInfo(String taskId); 999 1000}