Activiti 5.0 回退到任意节点(并行)

应用场景

​ 针对activiti中国式需求,实现平行网关回退

解决方案

任意节点回退思路
  1. 获取回退节点id,获取当前任务id
  2. 保存当前任务节点id流向
  3. 清除当前任务节点id流向
  4. 将当前任务节点任务流向退回节点id
  5. 完成当前节点任务
  6. 恢复当前节点流向
针对并行网关

在这里插入图片描述

处于并行网关内回退至网关外节点(如2.1回退到1),需考虑2.2是否已经完成,若已完成则不用管,若未完成,则需将2.2任务删除,否则会出现两个单

处于并行网关外回退至网关内节点(如3回退到2.1),需将2.2也回退,不然2.1通过后3不会创建新任务

核心代码

@Transactional(rollbackFor = Exception.class)
    public String backToAnyActivity(String taskId, String backToActivityId, String comment, Map<String, Object> variables) {
        if (this.isMultiInstance(taskId)) {
            throw new RenException(ErrorCode.REJECT_PROCESS_PARALLEL_ERROR);
        }
        //        用于保存历史审批人
        Map<String, String> historicAssigneeMap = new HashMap<>();
        HistoricTaskInstance currTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(currTask.getProcessInstanceId()).singleResult();
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(currTask.getProcessDefinitionId());
        if (processDefinitionEntity == null) {
            throw new RenException(ErrorCode.NONE_EXIST_PROCESS);
        }

        this.taskService.setVariablesLocal(taskId, variables);

        List<HistoricActivityInstance> backHistoricActivityInstances = historyService
                .createHistoricActivityInstanceQuery().activityType("userTask")
                .processInstanceId(processInstance.getId())
                .finished()
                .activityId(backToActivityId).list();
        if (backHistoricActivityInstances == null || backHistoricActivityInstances.isEmpty()) {
            throw new RuntimeException("不存在activity:" + backToActivityId);
        }


        List<Task> tasks = taskService.createTaskQuery().processInstanceId(currTask.getProcessInstanceId())
                .taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
        if (tasks.size() > 1) {
            throw new RenException(ErrorCode.REJECT_PROCESS_HANDLEING_ERROR);
        }
        ActivityImpl currActivity = processDefinitionEntity.findActivity(currTask.getTaskDefinitionKey());
        //判断是否要删除任务,默认不删除
        Boolean isDeleteTask = false;
        //        判断回退任务是否在并行任务中
        List<ActivityImpl> canBackActivitys = this.getCanBackUpActivityByParallelGateway(backToActivityId, processDefinitionEntity);
        if (canBackActivitys.size() == 0) {
            canBackActivitys = this.deleteCanBackUpActivityByParallelGateway(backToActivityId, processDefinitionEntity, currTask);
            isDeleteTask = true;
        }
        List<PvmTransition> originPvmTransitionList = new ArrayList<>();
        List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
        for (PvmTransition pvmTransition : pvmTransitionList) {
            originPvmTransitionList.add(pvmTransition);
        }
        pvmTransitionList.clear();
        List<HistoricActivityInstance> historicActivityInstances = historyService
                .createHistoricActivityInstanceQuery().activityType("userTask")
                .processInstanceId(processInstance.getId())
                .finished().orderByHistoricActivityInstanceEndTime().asc().list();
        //        获取历史审批人
        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
            historicAssigneeMap.put(historicActivityInstance.getActivityId(), historicActivityInstance.getAssignee());
        }

        List<TransitionImpl> transitions = new ArrayList<>();

//        退回任务
        if (historicActivityInstances.size() > 0) {
            ActivityImpl lastActivity = processDefinitionEntity.findActivity(backToActivityId);
            TransitionImpl transitionImpl = currActivity.createOutgoingTransition();
            transitionImpl.setDestination(lastActivity);
            transitions.add(transitionImpl);
        } else {
            throw new RenException(ErrorCode.SUPERIOR_NOT_EXIST);
        }
        List<String> ids = new ArrayList<>();
//        若为并行任务,将另一个任务也退回
        for (ActivityImpl canBackActivity : canBackActivitys) {
            if (!canBackActivity.getId().equals(backToActivityId)) {
                ActivityImpl otherActivity = processDefinitionEntity.findActivity(canBackActivity.getId());
                TransitionImpl transitionImpl = currActivity.createOutgoingTransition();
                transitionImpl.setDestination(otherActivity);
                transitions.add(transitionImpl);
//                用于同意任务
                ids.add(canBackActivity.getId());
            }
        }

        if (variables == null) {
            variables = processInstance.getProcessVariables();
        }

        for (Task task : tasks) {
            String commentMode = MessageUtils.getMessage(ErrorCode.ROLLBACK_MESSAGE);
            if (StringUtils.isNotEmpty(comment)) {
                commentMode += "[" + comment + "]";
            }
            //        清空之前保存的评论
            List<Comment> comments = taskService.getTaskComments(task.getId(), "comment");
            for (Comment com : comments) {
                taskService.deleteComment(com.getId());
            }
            taskService.addComment(task.getId(), task.getProcessInstanceId(), commentMode);
            taskService.complete(task.getId(), variables);
        }


        for (TransitionImpl transition : transitions) {
            currActivity.getOutgoingTransitions().remove(transition);
        }


        for (PvmTransition pvmTransition : originPvmTransitionList) {
            pvmTransitionList.add(pvmTransition);
        }

        //返回回退之后的任务id
        Task task = taskService.createTaskQuery()
                .processInstanceId(currTask.getProcessInstanceId())
                .processDefinitionId(currTask.getProcessDefinitionId())
                .taskDefinitionKey(backToActivityId)
                .singleResult();

        String assignee = historicAssigneeMap.get(backToActivityId);
        if (!"".equals(assignee) && assignee != null) {
            taskService.setAssignee(task.getId(), assignee);
        }
//        将其余并行任务结束
        for (String id : ids) {
            if (isDeleteTask) {
                List<Task> deleteTaskList = taskService.createTaskQuery()
                        .processInstanceId(currTask.getProcessInstanceId())
                        .processDefinitionId(currTask.getProcessDefinitionId())
                        .taskDefinitionKey(id)
                        .list();
                //删除任务
                for (Task deleteTask : deleteTaskList) {
                  //删除ru Execution 和 ru task 表字段
                }

            } else {
                if ((!id.equals(backToActivityId))) {
                    Task otherTask = taskService.createTaskQuery()
                            .processInstanceId(currTask.getProcessInstanceId())
                            .processDefinitionId(currTask.getProcessDefinitionId())
                            .taskDefinitionKey(id)
                            .singleResult();
                    if (otherTask == null){
                        continue;
                    }
                    String otherAssignee = historicAssigneeMap.get(id);
                    String otherTaskId = otherTask.getId();
                    taskService.addComment(otherTaskId, otherTask.getProcessInstanceId(), "[网关回退自动提交]");
                    taskService.setAssignee(otherTaskId, otherAssignee);
                    taskService.complete(otherTaskId);
                }

            }
        }
        return task.getId();
    }
/**
     * 结束节点回退到并行网关内部节点
     *
     * @param backToActivityId
     * @param processDefinitionEntity
     * @return
     */
    private List<ActivityImpl> getCanBackUpActivityByParallelGateway(String backToActivityId, ProcessDefinitionEntity processDefinitionEntity) {
        List<ActivityImpl> rtnList = new ArrayList<>();
        //        获取回退节点
        ActivityImpl backActivity = processDefinitionEntity.findActivity(backToActivityId);
        //        获取回退节点的下一个节点
        List<PvmTransition> outgoingTransitions = backActivity.getOutgoingTransitions();
//        判断下个节点是否为并行网关
        for (PvmTransition outgoingTransition : outgoingTransitions) {
            TransitionImpl transitionImpl = (TransitionImpl) outgoingTransition;
            ActivityImpl activityImpl = transitionImpl.getSource();
            String type = (String) activityImpl.getProperty("type");
//            是否有多个出口
            if (activityImpl.getOutgoingTransitions().size() > 1) {
                return rtnList;
            }
            if ("parallelGateway".equals(type)) {
//                获取并行网关的所有入口
                List<PvmTransition> incomingParallelGateway = activityImpl.getIncomingTransitions();
                for (PvmTransition pvmTransition : incomingParallelGateway) {
                    TransitionImpl transition = (TransitionImpl) pvmTransition;
                    ActivityImpl activity = transition.getSource();
                    if ("userTask".equals(activity.getProperty("type"))) {
                        rtnList.add(activity);
                    }
                }
            }
        }
        return rtnList;
    }

    /**
     * 并行网关内部节点回退到开始节点
     *
     * @param backToActivityId
     * @param processDefinitionEntity
     * @param currTask
     */
    public List<ActivityImpl> deleteCanBackUpActivityByParallelGateway(String backToActivityId, ProcessDefinitionEntity processDefinitionEntity, HistoricTaskInstance currTask) {
        //        获取回退节点
        ActivityImpl backActivity = processDefinitionEntity.findActivity(backToActivityId);
        //记录activity
        List<ActivityImpl> activityImpls = new ArrayList<>();
        List<PvmTransition> isParallelGateways = backActivity.getOutgoingTransitions();
        for (PvmTransition isParallelGateway : isParallelGateways) {
            TransitionImpl isTransitionParallelGateway = (TransitionImpl) isParallelGateway;
            ActivityImpl activityImpl = isTransitionParallelGateway.getDestination();
            if ("parallelGateway".equals(activityImpl.getProperty("type"))) {
                // 获取并行网关下的全部节点
                List<PvmTransition> outgoingTransitions = activityImpl.getOutgoingTransitions();
                for (PvmTransition outgoingTransition : outgoingTransitions) {
                    // 转为activityImpl
                    TransitionImpl transition = (TransitionImpl) outgoingTransition;
                    ActivityImpl activity = transition.getDestination();
                    if ("userTask".equals(activity.getProperty("type"))) {
                        //  并行回退自动
                        if (!currTask.getTaskDefinitionKey().equals(activity.getId())) {
                            Task task = taskService.createTaskQuery()
                                    .processInstanceId(currTask.getProcessInstanceId())
                                    .processDefinitionId(currTask.getProcessDefinitionId())
                                    .taskDefinitionKey(activity.getId())
                                    .singleResult();
                            if (task != null) {
                                activityImpls.add(activity);
                            }
                        }
                    }
                }
            }
        }
        return activityImpls;
    }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐