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<Void> {
|
|
private final String processInstanceId;
|
private final List<String> sourceTaskDefIdList;
|
private final List<String> targetFlowNodeIdList;
|
private final String deleteReason;
|
private final BpmnModel bpmnModel;
|
private final RuntimeService runtimeService;
|
private final Map<String, List<VariableInstanceEntity>> varMap = new ConcurrentHashMap<>();
|
|
public JumpCmd(String processInstanceId, List<String> sourceTaskDefIdList, List<String> 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<VariableInstanceEntity> 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<HistoricActivityInstance> 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<Execution> executionEntities = runtimeService.createExecutionQuery()
|
.processInstanceId(processInstanceId).activityId(str).list();
|
for (Execution parentExecution : executionEntities) {
|
List<ExecutionEntity> childExecutions = executionEntityManager.findChildExecutionsByParentExecutionId(parentExecution.getId());
|
for (ExecutionEntity childExecution : childExecutions) {
|
List<VariableInstanceEntity> 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<HistoricTaskInstance> 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<VariableInstanceEntity> variableInstances = variableService.findVariableInstancesByExecutionId(parentExecution.getId());
|
varMap.put(parentExecution.getActivityId(), variableInstances);
|
variableInstances.forEach(variableService::deleteVariableInstance);
|
ExecutionEntity parentExecutionEntity = (ExecutionEntity) parentExecution;
|
executionEntityManager.deleteExecutionAndRelatedData(parentExecutionEntity, deleteReason, false);
|
}
|
}
|
}
|
}
|