Activiti task return, arbitrary jump (task scheduling) function implementation and ideas (abbreviated version)

Activiti task return, arbitrary jump (task scheduling) function implementation and ideas (abbreviated version)

Original article: reprint please note: original article address

need:

          1. Return to the previous node at the current task node;
          2. After one or several nodes need to be skipped, the designated node starts to perform this task;
          3. Jump to any node when the process is running (you can jump whether it has been executed or not);

The idea of ​​this solution is the same way:

Simulate a requirement: nowNode jumps to toNode


Ideas:

1. Get all the lines (outGoingPath) connecting other nodes of the current node (here called nowNode) and save them, and then delete these lines;


2. Get the current node (nowNode) and the node of the specified jump (toNode), and then create a new line to connect the current node (nowNode) and the specified node (toNode);


3. Execute the task completion operation (at this time, because the current node has deleted the line originally connected to other nodes, there is only one line just connected to the current node (nowNode) and the specified node (toNode)), there is only one line, that is Say the task jumps to the specified node (toNode);
4. Restore the original flowchart (delete the new line, and restore the lines deleted on the original nowNode);

Here is the general idea, and then paste the code.

/**
 * Process turn operation
 *
 * @param taskId      current task ID
 * @param activityId target node task ID
 * @param variables   process variable
 * @throws Exception
 */
 public static void turnTransition (String taskId , String activityId , Map<String , Object> variables) {
     // Current node
     ActivityImpl currActivity = findActivitiImpl ( taskId , null ) ;
 // Clear current flow to
 List<PvmTransition> oriPvmTransitionList =        clearTransition (currActivity) ;
 // Create a new flow direction
 TransitionImpl newTransition = currActivity.createOutgoingTransition() ;
 // Target node
 ActivityImpl pointActivity = findActivitiImpl ( taskId , activityId) ;
 // Set the target node of the new flow direction
 newTransition.setDestination(pointActivity) ;
 // Execute the transition task
 taskService .complete(taskId , variables) ; // delete the target node new flow
 pointActivity.getIncomingTransitions().remove(newTransition) ;
 // restore the previous flow
 restoreTransition (currActivity , oriPvmTransitionList) ;
 }
                        
        
        
        
 
 
/**
 * Get active node based on task ID and node ID <br>
 *
 * @param taskId
 * @param activityId Active node ID <br>
 * If null or "", query the current active node by default <br>
 * If If it is "end", the query end node <br>
 * @return
 * @throws Exception
 */
 public static ActivityImpl findActivitiImpl (String taskId , String activityId) {
     // Get process definition
 ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService .getProcessDefinition( taskService          .createTaskQuery().taskId(taskId).singleResult().getProcessDefinitionId()) ;
 // Get the current activity node ID
 if (StringUtils. isEmpty (activityId)) {        
        activityId = getTaskById (taskId).getTaskDefinitionKey() ;
     }
     // According to the process definition, get the end node of the process instance
     ProcessDefinitionImpl processDefinitionImpl = (ProcessDefinitionImpl) getReadOnlyProcessDefinitionByProcDefId (processDefinition.getId()) ;
     if (activityId.toUpperCase().equals( "END" )) {
         for (ActivityImpl activityImpl : processDefinitionImpl.getActivities()) {
            List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
            if (pvmTransitionList.isEmpty()) {
                return activityImpl;
            }
        }
    }
    //According to the node ID, get the corresponding active node
     ActivityImpl activityImpl = processDefinitionImpl.findActivity(activityId) ;
 // Change here, the corresponding active node cannot be obtained, so a roundabout way is used here, if you can get it before, skip However, if you don't get it, get it yourself
 if (activityImpl == null ) {        
        List<ActivityImpl> activities = processDefinitionImpl.getActivities();
        for (ActivityImpl actImpl : activities) {
            if (actImpl.getId().equals(activityId)) {
                activityImpl = actImpl;
                break;
            }
        }
    }
    return activityImpl;
}
/**
 * 清空指定活动节点现有流向,且将清空的现有流向返回
 *
 * @param activityImpl 活动节点
 * @return 节点流向集合
 */
public static List<PvmTransition> clearTransition(ActivityImpl activityImpl) {
    // 存储当前节点所有流向临时变量
    List<PvmTransition> oriPvmTransitionList = new ArrayList<>();
    // 获取当前节点所有流向,存储到临时变量,然后清空
    List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
    for (PvmTransition pvmTransition : pvmTransitionList) {
        oriPvmTransitionList.add(pvmTransition);
    }
    pvmTransitionList.clear();

    return oriPvmTransitionList;
}
/**
 * 根据任务ID和节点ID获取活动节点 <br>
 *
 * @param taskId
 * @param activityId 活动节点ID <br>
 *                   如果为null或"",则默认查询当前活动节点 <br>
 *                   如果为"end",则查询结束节点 <br>
 * @return
 * @throws Exception
 */
public static ActivityImpl findActivitiImpl(String taskId, String activityId) {
    // 取得流程定义
    ProcessDefinitionEntity processDefinition = getProcDefEntityByTaskId(taskId);
    // 获取当前活动节点ID
    if (StringUtils.isEmpty(activityId)) {
        activityId = getTaskById(taskId).getTaskDefinitionKey();
    }
    // 根据流程定义,获取该流程实例的结束节点
    ProcessDefinitionImpl processDefinitionImpl = (ProcessDefinitionImpl) getReadOnlyProcessDefinitionByProcDefId(processDefinition.getId());
    if (activityId.toUpperCase().equals("END")) {
        for (ActivityImpl activityImpl : processDefinitionImpl.getActivities()) {
            List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
            if (pvmTransitionList.isEmpty()) {
                return activityImpl;
            }
        }
    }
    // 根据节点ID,获取对应的活动节点
    ActivityImpl activityImpl = processDefinitionImpl.findActivity(activityId);
    // 此处改动,无法获取到对应的活动节点,所以此处采用迂回的方式,如果前面可以取到则跳过,如果没有取到则自己取
    if (activityImpl == null) {
        List<ActivityImpl> activities = processDefinitionImpl.getActivities();
        for (ActivityImpl actImpl : activities) {
            if (actImpl.getId().equals(activityId)) {
                activityImpl = actImpl;
                break;
            }
        }
    }
    return activityImpl;
}
/**
 * 清空指定节点现有流向,且将新流向接入
 *
 * @param activityImpl         活动节点
 * @param oriPvmTransitionList 新流向节点集合
 */
public static void restoreTransition(ActivityImpl activityImpl, List<PvmTransition> oriPvmTransitionList) {
    // 清空现有流向
    List<PvmTransition> pvmTransitionList = activityImpl.getOutgoingTransitions();
    pvmTransitionList.clear();
    // 还原以前流向
    for (PvmTransition pvmTransition : oriPvmTransitionList) {
        pvmTransitionList.add(pvmTransition);
    }
}


ps:简版不涉及1.单任务回退并行节点(单变多);

        2.并行任务节点回退单任务节点(多变单);

        3.并行任务节点回退并行任务节点(多变多);

        4.并行多实例回退并行多实例任务(恶心);

    这些会留在以后的文章讲解。

            

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325523476&siteId=291194637