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