package jnpf.workflow.flowable.cmd; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.FlowNode; import org.flowable.common.engine.impl.interceptor.Command; import org.flowable.common.engine.impl.interceptor.CommandContext; import org.flowable.engine.RuntimeService; import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.impl.HistoricActivityInstanceQueryImpl; import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; import org.flowable.engine.impl.persistence.entity.HistoricActivityInstanceEntity; import org.flowable.engine.impl.util.CommandContextUtil; import org.flowable.engine.runtime.Execution; import org.flowable.task.api.history.HistoricTaskInstance; import org.flowable.task.service.HistoricTaskService; import org.flowable.task.service.impl.HistoricTaskInstanceQueryImpl; import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity; import org.flowable.variable.service.VariableService; import org.flowable.variable.service.impl.persistence.entity.VariableInstanceEntity; import cn.hutool.core.collection.CollectionUtil; /** * 自定义节点跳转命令:删除源节点执行流(含变量、历史任务标记), * 在目标节点重建子执行流并恢复变量,然后继续推进流程。 * 由黑盒 jar 反编译逐行保真还原,勿做"顺手优化"。 */ public class JumpCmd implements Command { private final String processInstanceId; private final List sourceTaskDefIdList; private final List targetFlowNodeIdList; private final String deleteReason; private final BpmnModel bpmnModel; private final RuntimeService runtimeService; private final Map> varMap = new ConcurrentHashMap<>(); public JumpCmd(String processInstanceId, List sourceTaskDefIdList, List targetFlowNodeIdList, String deleteReason, BpmnModel bpmnModel, RuntimeService runtimeService) { this.processInstanceId = processInstanceId; this.sourceTaskDefIdList = sourceTaskDefIdList; this.deleteReason = deleteReason; this.targetFlowNodeIdList = targetFlowNodeIdList; this.bpmnModel = bpmnModel; this.runtimeService = runtimeService; } @Override public Void execute(CommandContext commandContext) { ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); handleExecution(commandContext); handleActInst(commandContext); targetFlowNodeIdList.forEach(targetId -> { FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(targetId); ExecutionEntity processExecution = executionEntityManager.findById(processInstanceId); ExecutionEntity childExecution = executionEntityManager.createChildExecution(processExecution); childExecution.setCurrentFlowElement(flowNode); VariableService variableService = CommandContextUtil.getVariableService(); List variableInstanceEntities = varMap.get(flowNode.getId()); if (CollectionUtil.isNotEmpty(variableInstanceEntities)) { variableInstanceEntities.forEach(var -> { var.setExecutionId(childExecution.getId()); variableService.insertVariableInstance(var); }); } executionEntityManager.insert(childExecution); CommandContextUtil.getAgenda().planContinueProcessOperation(childExecution); }); return null; } private void handleActInst(CommandContext commandContext) { for (String str : sourceTaskDefIdList) { HistoricActivityInstanceQueryImpl query = (HistoricActivityInstanceQueryImpl) new HistoricActivityInstanceQueryImpl() .activityId(str).processInstanceId(processInstanceId).unfinished(); List activityInstances = CommandContextUtil.getHistoricActivityInstanceEntityManager().findHistoricActivityInstancesByQueryCriteria(query); for (HistoricActivityInstance activity : activityInstances) { HistoricActivityInstanceEntity activityEntity = (HistoricActivityInstanceEntity) activity; activityEntity.setDeleted(true); activityEntity.setDeleteReason(deleteReason); CommandContextUtil.getHistoricActivityInstanceEntityManager().update(activityEntity); } } } private void handleExecution(CommandContext commandContext) { ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); HistoricTaskService historicTaskService = CommandContextUtil.getHistoricTaskService(); VariableService variableService = CommandContextUtil.getVariableService(); for (String str : sourceTaskDefIdList) { List executionEntities = runtimeService.createExecutionQuery() .processInstanceId(processInstanceId).activityId(str).list(); for (Execution parentExecution : executionEntities) { List childExecutions = executionEntityManager.findChildExecutionsByParentExecutionId(parentExecution.getId()); for (ExecutionEntity childExecution : childExecutions) { List variableInstances = variableService.findVariableInstancesByExecutionId(childExecution.getId()); varMap.put(parentExecution.getActivityId(), variableInstances); variableInstances.forEach(variableService::deleteVariableInstance); executionEntityManager.deleteExecutionAndRelatedData(childExecution, deleteReason, false); HistoricTaskInstanceQueryImpl query = (HistoricTaskInstanceQueryImpl) new HistoricTaskInstanceQueryImpl() .executionId(childExecution.getId()).processInstanceId(processInstanceId); List historicTaskInstances = historicTaskService.findHistoricTaskInstancesByQueryCriteria(query); if (!CollectionUtil.isNotEmpty(historicTaskInstances)) { continue; } for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { HistoricTaskInstanceEntity entity = (HistoricTaskInstanceEntity) historicTaskInstance; entity.setDeleteReason(deleteReason); historicTaskService.updateHistoricTask(entity, true); } } List variableInstances = variableService.findVariableInstancesByExecutionId(parentExecution.getId()); varMap.put(parentExecution.getActivityId(), variableInstances); variableInstances.forEach(variableService::deleteVariableInstance); ExecutionEntity parentExecutionEntity = (ExecutionEntity) parentExecution; executionEntityManager.deleteExecutionAndRelatedData(parentExecutionEntity, deleteReason, false); } } } }