初始代码
This commit is contained in:
31
yunzhupaas-workflow-flowable/pom.xml
Normal file
31
yunzhupaas-workflow-flowable/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.yunzhupaas</groupId>
|
||||
<artifactId>yunzhupaas-workflow-core</artifactId>
|
||||
<version>1.0.0-RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>yunzhupaas-workflow-flowable</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-spring-boot-starter</artifactId>
|
||||
<version>${flowable.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.yunzhupaas</groupId>
|
||||
<artifactId>yunzhupaas-workflow-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<profiles>
|
||||
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.yunzhupaas.workflow.flowable.cmd;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
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 java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 跳转命令类
|
||||
* 参考:https://blog.csdn.net/zhsp419/article/details/114264451
|
||||
*
|
||||
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/9 17:45
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* 保存撤回节点的变量map
|
||||
*/
|
||||
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();
|
||||
// 处理act_ru_execution
|
||||
handleExecution(commandContext);
|
||||
// 处理act_hi_actinst
|
||||
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 = new HistoricActivityInstanceQueryImpl()
|
||||
.activityId(str).processInstanceId(processInstanceId).unfinished();
|
||||
List<HistoricActivityInstance> activityInstances = CommandContextUtil
|
||||
.getHistoricActivityInstanceEntityManager()
|
||||
.findHistoricActivityInstancesByQueryCriteria(query);
|
||||
for (HistoricActivityInstance activity : activityInstances) {
|
||||
HistoricActivityInstanceEntity activityEntity = (HistoricActivityInstanceEntity) activity;
|
||||
// 修改act_hi_actinst表
|
||||
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) {
|
||||
// 关闭未完成的任务执行流
|
||||
// 获取子级Executions,如子流程节点等需要处理
|
||||
List<ExecutionEntity> childExecutions = executionEntityManager
|
||||
.findChildExecutionsByParentExecutionId(parentExecution.getId());
|
||||
for (ExecutionEntity childExecution : childExecutions) {
|
||||
// 因为外键约束,首先要删除variable表中的execution相关数据
|
||||
List<VariableInstanceEntity> variableInstances = variableService
|
||||
.findVariableInstancesByExecutionId(childExecution.getId());
|
||||
varMap.put(parentExecution.getActivityId(), variableInstances);
|
||||
variableInstances.forEach(variableService::deleteVariableInstance);
|
||||
executionEntityManager.deleteExecutionAndRelatedData(childExecution, deleteReason, false);
|
||||
// 修改历史实例
|
||||
HistoricTaskInstanceQueryImpl query = new HistoricTaskInstanceQueryImpl()
|
||||
.executionId(childExecution.getId()).processInstanceId(processInstanceId);
|
||||
List<HistoricTaskInstance> HistoricTaskInstances = historicTaskService
|
||||
.findHistoricTaskInstancesByQueryCriteria(query);
|
||||
if (CollectionUtil.isNotEmpty(HistoricTaskInstances)) {
|
||||
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 parentExecution1 = (ExecutionEntity) parentExecution;
|
||||
executionEntityManager.deleteExecutionAndRelatedData(parentExecution1, deleteReason, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.yunzhupaas.workflow.flowable.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yunzhupaas.workflow.common.exception.BizException;
|
||||
import com.yunzhupaas.workflow.common.exception.ResultCode;
|
||||
import com.yunzhupaas.workflow.common.model.fo.DefinitionDeleteFo;
|
||||
import com.yunzhupaas.workflow.common.model.fo.DefinitionDeployFo;
|
||||
import com.yunzhupaas.workflow.common.model.vo.DefinitionVo;
|
||||
import com.yunzhupaas.workflow.common.model.vo.DeploymentVo;
|
||||
import com.yunzhupaas.workflow.common.model.vo.FlowElementVo;
|
||||
import com.yunzhupaas.workflow.common.service.IDefinitionService;
|
||||
import com.yunzhupaas.workflow.flowable.util.FlowableUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 流程定义实现层
|
||||
*
|
||||
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/3 11:36
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class DefinitionServiceImpl implements IDefinitionService {
|
||||
private final RepositoryService repositoryService;
|
||||
|
||||
@Override
|
||||
public DeploymentVo deployDefinition(DefinitionDeployFo fo) {
|
||||
Deployment deployment;
|
||||
try {
|
||||
String resourceName;
|
||||
if (StrUtil.isNotBlank(fo.getKey())) {
|
||||
resourceName = fo.getKey();
|
||||
} else {
|
||||
resourceName = IdUtil.getSnowflakeNextIdStr();
|
||||
}
|
||||
deployment = repositoryService
|
||||
.createDeployment()
|
||||
.name(fo.getName())
|
||||
.key(fo.getKey())
|
||||
.addString(resourceName + ".bpmn20.xml", fo.getBpmnXml())
|
||||
.disableSchemaValidation()
|
||||
.deploy();
|
||||
} catch (Exception e) {
|
||||
throw new BizException(ResultCode.DEPLOY_ERROR.getMsg(), e);
|
||||
}
|
||||
DeploymentVo vo = new DeploymentVo();
|
||||
vo.setDeploymentId(deployment.getId());
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DefinitionVo> listDefinition() {
|
||||
List<ProcessDefinition> definitions = repositoryService.createProcessDefinitionQuery().list();
|
||||
List<DefinitionVo> list = new ArrayList<>();
|
||||
if (CollectionUtil.isNotEmpty(definitions)) {
|
||||
for (ProcessDefinition definition : definitions) {
|
||||
DefinitionVo vo = new DefinitionVo();
|
||||
vo.setDefinitionId(definition.getId());
|
||||
vo.setDefinitionName(definition.getName());
|
||||
vo.setDefinitionKey(definition.getKey());
|
||||
vo.setDefinitionVersion(definition.getVersion());
|
||||
vo.setDeploymentId(definition.getDeploymentId());
|
||||
list.add(vo);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteDefinition(DefinitionDeleteFo fo) {
|
||||
if (null == fo.getCascade()) {
|
||||
fo.setCascade(true);
|
||||
}
|
||||
try {
|
||||
// 根据部署ID删除,并级联删除当前流程定义下的所有流程实例、job
|
||||
repositoryService.deleteDeployment(fo.getDeploymentId(), fo.getCascade());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(ResultCode.DELETE_FAILURE.getMsg(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowElementVo> getStructure(String deploymentId) {
|
||||
List<FlowElementVo> vos = new ArrayList<>();
|
||||
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId)
|
||||
.singleResult();
|
||||
if (null != definition) {
|
||||
Process process = repositoryService.getBpmnModel(definition.getId()).getProcesses().get(0);
|
||||
Collection<FlowElement> elements = FlowableUtil.getAllElements(process.getFlowElements(), null);
|
||||
for (FlowElement element : elements) {
|
||||
FlowElementVo vo = BeanUtil.copyProperties(element, FlowElementVo.class);
|
||||
if (element instanceof Event) {
|
||||
Event el = (Event) element;
|
||||
vo.setIncomingList(
|
||||
el.getIncomingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
vo.setOutgoingList(
|
||||
el.getOutgoingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
}
|
||||
if (element instanceof Activity) {
|
||||
Activity el = (Activity) element;
|
||||
vo.setIncomingList(
|
||||
el.getIncomingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
vo.setOutgoingList(
|
||||
el.getOutgoingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
}
|
||||
if (element instanceof Gateway) {
|
||||
Gateway el = (Gateway) element;
|
||||
vo.setIncomingList(
|
||||
el.getIncomingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
vo.setOutgoingList(
|
||||
el.getOutgoingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
}
|
||||
vos.add(vo);
|
||||
}
|
||||
}
|
||||
|
||||
return vos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.yunzhupaas.workflow.flowable.service;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.yunzhupaas.workflow.common.exception.BizException;
|
||||
import com.yunzhupaas.workflow.common.exception.ResultCode;
|
||||
import com.yunzhupaas.workflow.common.model.fo.InstanceDeleteFo;
|
||||
import com.yunzhupaas.workflow.common.model.fo.InstanceStartFo;
|
||||
import com.yunzhupaas.workflow.common.model.vo.HistoricInstanceVo;
|
||||
import com.yunzhupaas.workflow.common.model.vo.InstanceVo;
|
||||
import com.yunzhupaas.workflow.common.service.IInstanceService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.ZoneId;
|
||||
|
||||
/**
|
||||
* 流程实例实现层
|
||||
*
|
||||
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/7 14:34
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class InstanceServiceImpl implements IInstanceService {
|
||||
private final RepositoryService repositoryService;
|
||||
private final RuntimeService runtimeService;
|
||||
private final HistoryService historyService;
|
||||
|
||||
@Override
|
||||
public InstanceVo startById(InstanceStartFo fo) {
|
||||
ProcessDefinition definition = repositoryService
|
||||
.createProcessDefinitionQuery()
|
||||
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
InstanceVo vo = new InstanceVo();
|
||||
ProcessInstance instance;
|
||||
if (CollectionUtil.isNotEmpty(fo.getVariables())) {
|
||||
instance = runtimeService.startProcessInstanceById(definition.getId(), fo.getVariables());
|
||||
} else {
|
||||
instance = runtimeService.startProcessInstanceById(definition.getId());
|
||||
}
|
||||
if (null != instance) {
|
||||
vo.setInstanceId(instance.getId());
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoricInstanceVo getHistoricProcessInstance(String processInstanceId) {
|
||||
HistoricProcessInstance historicInstance = historyService
|
||||
.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.singleResult();
|
||||
if (null == historicInstance) {
|
||||
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||
}
|
||||
HistoricInstanceVo vo = new HistoricInstanceVo();
|
||||
vo.setInstanceId(historicInstance.getId());
|
||||
vo.setStartTime(historicInstance.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
|
||||
vo.setEndTime(historicInstance.getEndTime() == null ? null
|
||||
: historicInstance.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
|
||||
vo.setDurationInMillis(historicInstance.getDurationInMillis());
|
||||
vo.setDeleteReason(historicInstance.getDeleteReason());
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteInstance(InstanceDeleteFo fo) {
|
||||
try {
|
||||
runtimeService.deleteProcessInstance(fo.getInstanceId(), fo.getDeleteReason());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(ResultCode.DELETE_FAILURE.getMsg(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,619 @@
|
||||
package com.yunzhupaas.workflow.flowable.service;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yunzhupaas.workflow.common.exception.BizException;
|
||||
import com.yunzhupaas.workflow.common.exception.ResultCode;
|
||||
import com.yunzhupaas.workflow.common.model.fo.*;
|
||||
import com.yunzhupaas.workflow.common.model.vo.*;
|
||||
import com.yunzhupaas.workflow.common.service.IInstanceService;
|
||||
import com.yunzhupaas.workflow.common.service.ITaskService;
|
||||
import com.yunzhupaas.workflow.flowable.cmd.JumpCmd;
|
||||
import com.yunzhupaas.workflow.flowable.util.FlowableUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.constants.BpmnXMLConstants;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.engine.*;
|
||||
import org.flowable.engine.history.HistoricActivityInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.TaskInfo;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.flowable.variable.api.history.HistoricVariableInstance;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 流程任务实现层
|
||||
*
|
||||
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/8 11:12
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class TaskServiceImpl implements ITaskService {
|
||||
private final TaskService taskService;
|
||||
private final HistoryService historyService;
|
||||
private final RuntimeService runtimeService;
|
||||
private final RepositoryService repositoryService;
|
||||
private final ManagementService managementService;
|
||||
private final IInstanceService instanceService;
|
||||
|
||||
@Override
|
||||
public List<TaskVo> getTask(String instanceId) {
|
||||
List<Task> list = taskService.createTaskQuery().processInstanceId(instanceId).list();
|
||||
List<TaskVo> vos = new ArrayList<>();
|
||||
if (CollectionUtil.isNotEmpty(list)) {
|
||||
for (Task task : list) {
|
||||
TaskVo vo = new TaskVo();
|
||||
vo.setTaskId(task.getId());
|
||||
vo.setTaskName(task.getName());
|
||||
vo.setTaskKey(task.getTaskDefinitionKey());
|
||||
vo.setInstanceId(task.getProcessInstanceId());
|
||||
vos.add(vo);
|
||||
}
|
||||
}
|
||||
return vos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean complete(TaskCompleteFo fo) {
|
||||
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||
if (null == task) {
|
||||
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||
}
|
||||
try {
|
||||
if (CollectionUtil.isNotEmpty(fo.getVariables())) {
|
||||
taskService.complete(fo.getTaskId(), fo.getVariables());
|
||||
} else {
|
||||
taskService.complete(fo.getTaskId());
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(ResultCode.TASK_COMPLETE_ERROR.getMsg(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveSingleToMulti(MoveSingleToMultiFo fo) {
|
||||
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(fo.getInstanceId())
|
||||
.singleResult();
|
||||
if (null == instance) {
|
||||
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||
}
|
||||
try {
|
||||
this.moveSingleActivityIdToActivityIds(fo.getInstanceId(), fo.getSourceKey(), fo.getTargetKeys());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(ResultCode.TASK_JUMP_ERROR.getMsg(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点跳转
|
||||
* Set the activity id that should be changed to multiple activity ids
|
||||
*/
|
||||
public void moveSingleActivityIdToActivityIds(String processInstanceId, String activityId,
|
||||
List<String> activityIds) {
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.processInstanceId(processInstanceId)
|
||||
.moveSingleActivityIdToActivityIds(activityId, activityIds).changeState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveMultiToSingle(MoveMultiToSingleFo fo) {
|
||||
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(fo.getInstanceId())
|
||||
.singleResult();
|
||||
if (null == instance) {
|
||||
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||
}
|
||||
try {
|
||||
this.moveActivityIdsToSingleActivityId(fo.getInstanceId(), fo.getSourceKeys(), fo.getTargetKey());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(ResultCode.TASK_JUMP_ERROR.getMsg(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点跳转
|
||||
* Set the activity ids that should be changed to a single activity id
|
||||
*/
|
||||
public void moveActivityIdsToSingleActivityId(String processInstanceId, List<String> activityIds,
|
||||
String activityId) {
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.processInstanceId(processInstanceId)
|
||||
.moveActivityIdsToSingleActivityId(activityIds, activityId).changeState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean jump(JumpFo fo) {
|
||||
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(fo.getInstanceId())
|
||||
.singleResult();
|
||||
if (null == instance) {
|
||||
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||
}
|
||||
try {
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
|
||||
JumpCmd jumpCmd = new JumpCmd(fo.getInstanceId(), fo.getSource(), fo.getTarget(), "custom jump", bpmnModel,
|
||||
runtimeService);
|
||||
managementService.executeCommand(jumpCmd);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(ResultCode.TASK_JUMP_ERROR.getMsg(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFallbacks(String taskId) {
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
if (null == task) {
|
||||
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||
}
|
||||
FlowElement source = getFlowElement(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
List<String> list = FlowableUtil.getPassActs(source, null, null);
|
||||
return list.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程定义ID和任务KEY 获取节点元素
|
||||
*/
|
||||
public FlowElement getFlowElement(String processDefinitionId, String taskDefinitionKey) {
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||
.processDefinitionId(processDefinitionId).singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
Process process = repositoryService.getBpmnModel(definition.getId()).getProcesses().get(0);
|
||||
Collection<FlowElement> elements = FlowableUtil.getAllElements(process.getFlowElements(), null);
|
||||
FlowElement source = null;
|
||||
if (null != elements && !elements.isEmpty()) {
|
||||
for (FlowElement element : elements) {
|
||||
if (element.getId().equals(taskDefinitionKey)) {
|
||||
source = element;
|
||||
}
|
||||
}
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> back(TaskBackFo fo) {
|
||||
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||
String definitionId;
|
||||
String instanceId;
|
||||
if (null == task) {
|
||||
HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery().taskId(fo.getTaskId())
|
||||
.singleResult();
|
||||
definitionId = historicTask.getProcessDefinitionId();
|
||||
instanceId = historicTask.getProcessInstanceId();
|
||||
} else {
|
||||
definitionId = task.getProcessDefinitionId();
|
||||
instanceId = task.getProcessInstanceId();
|
||||
}
|
||||
if (StrUtil.isNotBlank(fo.getTargetKey())) {
|
||||
String[] split = fo.getTargetKey().split(",");
|
||||
if (split.length == 0) {
|
||||
throw new BizException("目标节点编码不能为空");
|
||||
}
|
||||
List<String> list = Arrays.asList(split);
|
||||
return this.back(definitionId, instanceId, list);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> back(String definitionId, String instanceId, List<String> targetList) {
|
||||
List<String> currentIds = new ArrayList<>();
|
||||
for (String targetKey : targetList) {
|
||||
FlowElement target = getFlowElement(definitionId, targetKey);
|
||||
// 获取所有正常进行的任务节点Key,用于找出需要撤回的任务
|
||||
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(instanceId).list();
|
||||
List<String> runTaskKeyList = runTaskList.stream().map(Task::getTaskDefinitionKey)
|
||||
.collect(Collectors.toList());
|
||||
// 需驳回的任务列表
|
||||
List<UserTask> userTaskList = FlowableUtil.getChildUserTasks(target, runTaskKeyList, null, null);
|
||||
List<String> collect = userTaskList.stream().map(UserTask::getId).collect(Collectors.toList());
|
||||
currentIds.addAll(collect);
|
||||
}
|
||||
currentIds = currentIds.stream().distinct().collect(Collectors.toList());
|
||||
|
||||
JumpFo jumpFo = new JumpFo();
|
||||
jumpFo.setInstanceId(instanceId);
|
||||
jumpFo.setSource(currentIds);
|
||||
jumpFo.setTarget(targetList);
|
||||
this.jump(jumpFo);
|
||||
|
||||
return currentIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPrevUserTask(TaskPrevFo fo) {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (StrUtil.isNotBlank(fo.getDeploymentId())) {
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
// 获取当前节点
|
||||
FlowElement source = getFlowElement(definition.getId(), fo.getTaskKey());
|
||||
// 获取下一级用户任务
|
||||
list = FlowableUtil.getParentActs(source, null, null);
|
||||
} else {
|
||||
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||
if (null == task) {
|
||||
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||
}
|
||||
FlowElement source = getFlowElement(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
list = FlowableUtil.getParentActs(source, null, null);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NodeElementVo> getNextUserTask(TaskNextFo fo) {
|
||||
List<UserTask> nextUserTasks = new ArrayList<>();
|
||||
if (StrUtil.isNotBlank(fo.getDeploymentId())) {
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
// 获取当前节点
|
||||
FlowElement source = getFlowElement(definition.getId(), fo.getTaskKey());
|
||||
// 获取下一级用户任务
|
||||
nextUserTasks = FlowableUtil.getNextUserTasks(source, null, null);
|
||||
} else {
|
||||
HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery().taskId(fo.getTaskId())
|
||||
.singleResult();
|
||||
if (null == taskInst) {
|
||||
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||
}
|
||||
FlowElement source = getFlowElement(taskInst.getProcessDefinitionId(), taskInst.getTaskDefinitionKey());
|
||||
// 获取下一级用户任务
|
||||
nextUserTasks = FlowableUtil.getNextUserTasks(source, null, null);
|
||||
}
|
||||
List<NodeElementVo> vos = new ArrayList<>();
|
||||
if (CollectionUtil.isNotEmpty(nextUserTasks)) {
|
||||
for (UserTask task : nextUserTasks) {
|
||||
NodeElementVo vo = new NodeElementVo();
|
||||
vo.setId(task.getId());
|
||||
vo.setName(task.getName());
|
||||
vo.setIncomingList(
|
||||
task.getIncomingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
vo.setOutgoingList(
|
||||
task.getOutgoingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
vos.add(vo);
|
||||
}
|
||||
}
|
||||
return vos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTaskKeyAfterFlow(FlowTargetTaskFo fo) {
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
List<String> list = new ArrayList<>();
|
||||
// 获取当前节点
|
||||
FlowElement source = getFlowElement(definition.getId(), fo.getFlowKey());
|
||||
String taskKey = FlowableUtil.getTaskKeyAfterFlow(source);
|
||||
list.add(taskKey);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retract(String taskId) {
|
||||
// 需要撤回的任务实例
|
||||
HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
|
||||
if (null != taskInst) {
|
||||
ProcessInstance procInst = runtimeService.createProcessInstanceQuery()
|
||||
.processInstanceId(taskInst.getProcessInstanceId())
|
||||
.active().singleResult();
|
||||
if (null != procInst) {
|
||||
// 获取当前节点
|
||||
FlowElement source = getFlowElement(taskInst.getProcessDefinitionId(), taskInst.getTaskDefinitionKey());
|
||||
// 获取下一级用户任务
|
||||
List<UserTask> nextUserTasks = FlowableUtil.getNextUserTasks(source, null, null);
|
||||
List<String> nextUserTaskKeys = nextUserTasks.stream().map(UserTask::getId)
|
||||
.collect(Collectors.toList());
|
||||
// 获取所有运行的任务节点,找到需要撤回的任务
|
||||
List<Task> activateTasks = taskService.createTaskQuery()
|
||||
.processInstanceId(taskInst.getProcessInstanceId()).list();
|
||||
List<String> currentIds = new ArrayList<>();
|
||||
for (Task task : activateTasks) {
|
||||
// 检查激活的任务节点是否存在下一级中,如果存在,则加入到需要撤回的节点
|
||||
if (CollUtil.contains(nextUserTaskKeys, task.getTaskDefinitionKey())) {
|
||||
currentIds.add(task.getTaskDefinitionKey());
|
||||
}
|
||||
}
|
||||
this.moveActivityIdsToSingleActivityId(taskInst.getProcessInstanceId(), currentIds,
|
||||
taskInst.getTaskDefinitionKey());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOutgoingFlows(TaskOutgoingFo fo) {
|
||||
if (StrUtil.isNotBlank(fo.getDeploymentId())) {
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
return this.getOutgoingFlows(definition.getId(), fo.getTaskKey());
|
||||
} else {
|
||||
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||
if (null == task) {
|
||||
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||
}
|
||||
return this.getOutgoingFlows(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取出线Key集合(若出线的出口为网关,则一并获取网关的出线)
|
||||
*/
|
||||
public List<String> getOutgoingFlows(String processDefinitionId, String taskDefinitionKey) {
|
||||
FlowElement source = getFlowElement(processDefinitionId, taskDefinitionKey);
|
||||
List<SequenceFlow> flows = new ArrayList<>();
|
||||
flows = FlowableUtil.getOutFlowsWithGateway(source, flows);
|
||||
List<String> list = new ArrayList<>();
|
||||
if (!flows.isEmpty()) {
|
||||
for (SequenceFlow flow : flows) {
|
||||
list.add(flow.getId());
|
||||
}
|
||||
}
|
||||
return list.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowVo> getOutgoing(TaskOutgoingFo fo) {
|
||||
if (StrUtil.isNotBlank(fo.getDeploymentId())) {
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
return this.getOutgoing(definition.getId(), fo.getTaskKey());
|
||||
} else {
|
||||
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||
if (null == task) {
|
||||
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||
}
|
||||
return this.getOutgoing(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
}
|
||||
}
|
||||
|
||||
public List<FlowVo> getOutgoing(String processDefinitionId, String taskDefinitionKey) {
|
||||
FlowElement source = getFlowElement(processDefinitionId, taskDefinitionKey);
|
||||
return FlowableUtil.getOutFlows(source, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getKeysOfFinished(String instanceId) {
|
||||
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId)
|
||||
.singleResult();
|
||||
if (null == instance) {
|
||||
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||
}
|
||||
// 获取当前节点之前的节点
|
||||
List<String> keysOfBefore = getKeysOfBefore(instance);
|
||||
// 获取流程实例下完成的历史活动
|
||||
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(instanceId).finished().list();
|
||||
if (CollectionUtil.isNotEmpty(list)) {
|
||||
// 去除线,并去重
|
||||
List<String> keysOfFinished = list.stream()
|
||||
.filter(e -> !BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW.equals(e.getActivityType()))
|
||||
.sorted(Comparator.comparing(HistoricActivityInstance::getStartTime))
|
||||
.map(HistoricActivityInstance::getActivityId)
|
||||
.distinct().collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(keysOfBefore)) {
|
||||
keysOfFinished.retainAll(keysOfBefore);
|
||||
}
|
||||
return keysOfFinished;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历当前节点,获取之前的节点
|
||||
*/
|
||||
public List<String> getKeysOfBefore(ProcessInstance instance) {
|
||||
List<String> res = new ArrayList<>();
|
||||
// 获取实例下的当前任务
|
||||
List<Task> taskList = taskService.createTaskQuery().processInstanceId(instance.getId()).list();
|
||||
if (CollectionUtil.isNotEmpty(taskList)) {
|
||||
List<String> keys = taskList.stream().map(TaskInfo::getTaskDefinitionKey).collect(Collectors.toList());
|
||||
for (String key : keys) {
|
||||
FlowElement source = getFlowElement(instance.getProcessDefinitionId(), key);
|
||||
List<String> list = FlowableUtil.getBefore(source, null, null);
|
||||
res.addAll(list);
|
||||
}
|
||||
}
|
||||
return res.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getIncomingFlows(String taskId) {
|
||||
HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
|
||||
if (null != taskInst) {
|
||||
FlowElement source = getFlowElement(taskInst.getProcessDefinitionId(), taskInst.getTaskDefinitionKey());
|
||||
List<SequenceFlow> flows = FlowableUtil.getElementIncomingFlows(source);
|
||||
return flows.stream().map(BaseElement::getId).collect(Collectors.toList());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取未经过的节点
|
||||
@Override
|
||||
public List<String> getToBePass(String instanceId) {
|
||||
List<String> list = new ArrayList<>();
|
||||
List<Task> currentList = taskService.createTaskQuery().processInstanceId(instanceId).list();
|
||||
if (CollectionUtil.isNotEmpty(currentList)) {
|
||||
List<String> collect = currentList.stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList());
|
||||
// 根据当前的节点 递归后续的所有节点
|
||||
for (Task task : currentList) {
|
||||
FlowElement source = getFlowElement(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
List<String> after = FlowableUtil.getAfter(source, null, null);
|
||||
list.addAll(after);
|
||||
}
|
||||
list = list.stream().filter(e -> !collect.contains(e)).collect(Collectors.toList());
|
||||
}
|
||||
return list.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAfter(TaskAfterFo fo) {
|
||||
String deploymentId = fo.getDeploymentId();
|
||||
List<String> taskKeys = fo.getTaskKeys();
|
||||
List<String> list = new ArrayList<>();
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId)
|
||||
.singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
for (String taskKey : taskKeys) {
|
||||
FlowElement source = getFlowElement(definition.getId(), taskKey);
|
||||
List<String> after = FlowableUtil.getAfter(source, null, null);
|
||||
list.addAll(after);
|
||||
}
|
||||
return list.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// complete 异常 补偿
|
||||
@Override
|
||||
public List<TaskVo> compensate(CompensateFo fo) {
|
||||
String instanceId = fo.getInstanceId();
|
||||
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId)
|
||||
.singleResult();
|
||||
if (null == instance) {
|
||||
HistoricProcessInstance historicInstance = historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(instanceId).singleResult();
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery()
|
||||
.processInstanceId(instanceId).list();
|
||||
for (HistoricVariableInstance var : list) {
|
||||
variables.put(var.getVariableName(), var.getValue());
|
||||
}
|
||||
String deploymentId = historicInstance.getDeploymentId();
|
||||
|
||||
InstanceStartFo startFo = new InstanceStartFo();
|
||||
startFo.setDeploymentId(deploymentId);
|
||||
startFo.setVariables(variables);
|
||||
InstanceVo instanceVo = instanceService.startById(startFo);
|
||||
instanceId = instanceVo.getInstanceId();
|
||||
}
|
||||
List<String> sourceList = fo.getSource().stream().sorted().collect(Collectors.toList());
|
||||
|
||||
List<TaskVo> taskVoList = this.getTask(instanceId);
|
||||
List<String> currentList = taskVoList.stream().map(TaskVo::getTaskKey).sorted().collect(Collectors.toList());
|
||||
|
||||
// if (ObjectUtil.equals(sourceList, currentList)) {
|
||||
// return null == instance ? taskVoList : new ArrayList<>();
|
||||
// }
|
||||
|
||||
// 获取需要跳转的节点集合、目标节点集合
|
||||
List<String> createList = sourceList.stream().filter(e -> !currentList.contains(e))
|
||||
.collect(Collectors.toList());
|
||||
List<String> deleteList = currentList.stream().filter(e -> !sourceList.contains(e))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
JumpFo jumpFo = new JumpFo();
|
||||
jumpFo.setInstanceId(instanceId);
|
||||
jumpFo.setSource(deleteList);
|
||||
jumpFo.setTarget(createList);
|
||||
this.jump(jumpFo);
|
||||
|
||||
List<TaskVo> vos = this.getTask(instanceId);
|
||||
if (null != instance) {
|
||||
vos.forEach(e -> e.setInstanceId(null));
|
||||
}
|
||||
return vos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HistoricNodeVo> getHistoric(String instanceId) {
|
||||
List<HistoricNodeVo> vos;
|
||||
|
||||
Set<String> set = new HashSet<>();
|
||||
set.add("userTask");
|
||||
set.add("startEvent");
|
||||
|
||||
vos = this.getHistoricVos(instanceId, set);
|
||||
|
||||
return vos.stream().sorted(Comparator.comparing(HistoricNodeVo::getStartTime)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 获取历史结束节点
|
||||
@Override
|
||||
public List<String> getHistoricEnd(String instanceId) {
|
||||
List<String> list = new ArrayList<>();
|
||||
List<HistoricNodeVo> vos = this.getHistoricVos(instanceId, null);
|
||||
if (CollectionUtil.isNotEmpty(vos)) {
|
||||
list = vos.stream().map(HistoricNodeVo::getCode).distinct().collect(Collectors.toList());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<HistoricNodeVo> getHistoricVos(String instanceId, Set<String> set) {
|
||||
List<HistoricNodeVo> vos = new ArrayList<>();
|
||||
if (CollectionUtil.isEmpty(set)) {
|
||||
set = new HashSet<>();
|
||||
set.add("endEvent");
|
||||
}
|
||||
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
|
||||
.activityTypes(set)
|
||||
.processInstanceId(instanceId).list();
|
||||
if (CollectionUtil.isNotEmpty(list)) {
|
||||
for (HistoricActivityInstance act : list) {
|
||||
HistoricNodeVo vo = new HistoricNodeVo();
|
||||
vo.setCode(act.getActivityId());
|
||||
vo.setTaskId(act.getTaskId());
|
||||
vo.setStartTime(act.getStartTime().getTime());
|
||||
vos.add(vo);
|
||||
}
|
||||
}
|
||||
return vos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeElementVo getElementInfo(InfoModel model) {
|
||||
String deploymentId = model.getDeploymentId();
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId)
|
||||
.singleResult();
|
||||
if (null == definition) {
|
||||
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||
}
|
||||
String definitionId = definition.getId();
|
||||
String key = model.getKey();
|
||||
NodeElementVo vo = new NodeElementVo();
|
||||
FlowElement source = getFlowElement(definitionId, key);
|
||||
if (null != source) {
|
||||
vo.setId(source.getId());
|
||||
List<SequenceFlow> outgoingFlows = FlowableUtil.getElementOutgoingFlows(source);
|
||||
vo.setOutgoingList(outgoingFlows.stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
List<SequenceFlow> incomingFlows = FlowableUtil.getElementIncomingFlows(source);
|
||||
vo.setIncomingList(incomingFlows.stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
package com.yunzhupaas.workflow.flowable.util;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.yunzhupaas.workflow.common.model.vo.FlowVo;
|
||||
import org.flowable.bpmn.model.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* flowable工具类
|
||||
*
|
||||
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/8 11:06
|
||||
*/
|
||||
public class FlowableUtil {
|
||||
/**
|
||||
* 获取全部节点元素
|
||||
*
|
||||
* @param flowElements {@link Collection<FlowElement>}
|
||||
* @param allElements {@link Collection<FlowElement>}
|
||||
* @return {@link Collection<FlowElement>}
|
||||
* @since 2024/4/8 11:07
|
||||
**/
|
||||
public static Collection<FlowElement> getAllElements(Collection<FlowElement> flowElements,
|
||||
Collection<FlowElement> allElements) {
|
||||
allElements = allElements == null ? new ArrayList<>() : allElements;
|
||||
for (FlowElement flowElement : flowElements) {
|
||||
allElements.add(flowElement);
|
||||
if (flowElement instanceof SubProcess) {
|
||||
// 获取子流程元素
|
||||
allElements = getAllElements(((SubProcess) flowElement).getFlowElements(), allElements);
|
||||
}
|
||||
}
|
||||
return allElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点的入口连线
|
||||
*
|
||||
* @param element {@link FlowElement}
|
||||
* @return {@link List<SequenceFlow>}
|
||||
* @since 2024/4/8 11:10
|
||||
**/
|
||||
public static List<SequenceFlow> getElementIncomingFlows(FlowElement element) {
|
||||
List<SequenceFlow> flows = null;
|
||||
if (element instanceof FlowNode) {
|
||||
flows = ((FlowNode) element).getIncomingFlows();
|
||||
}
|
||||
return flows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点的出口连线
|
||||
*
|
||||
* @param element {@link FlowElement}
|
||||
* @return {@link List<SequenceFlow>}
|
||||
* @since 2024/4/8 11:10
|
||||
**/
|
||||
public static List<SequenceFlow> getElementOutgoingFlows(FlowElement element) {
|
||||
List<SequenceFlow> flows = null;
|
||||
if (element instanceof FlowNode) {
|
||||
flows = ((FlowNode) element).getOutgoingFlows();
|
||||
}
|
||||
return flows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可回退的节点(仅用户任务)
|
||||
*
|
||||
* @param source {@link FlowElement}
|
||||
* @param passFlows {@link Set<String>}
|
||||
* @param passActs {@link List<String>}
|
||||
* @return {@link List<String>}
|
||||
* @since 2024/4/8 15:27
|
||||
**/
|
||||
public static List<String> getPassActs(FlowElement source, Set<String> passFlows, List<String> passActs) {
|
||||
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||
passActs = passActs == null ? new ArrayList<>() : passActs;
|
||||
|
||||
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||
if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
// 连线重复
|
||||
if (passFlows.contains(sequenceFlow.getId())) {
|
||||
continue;
|
||||
}
|
||||
// 添加经过的连线
|
||||
passFlows.add(sequenceFlow.getId());
|
||||
// 添加经过的用户任务
|
||||
if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
|
||||
passActs.add(sequenceFlow.getSourceFlowElement().getId());
|
||||
}
|
||||
if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
|
||||
passActs.add(sequenceFlow.getSourceFlowElement().getId());
|
||||
continue;
|
||||
}
|
||||
// 迭代
|
||||
getPassActs(sequenceFlow.getSourceFlowElement(), passFlows, passActs);
|
||||
}
|
||||
}
|
||||
return passActs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取需要撤回的节点
|
||||
*
|
||||
* @param source {@link FlowElement}
|
||||
* @param runTaskKeyList {@link List<String>}
|
||||
* @param passFlows {@link Set<String>}
|
||||
* @param userTasks {@link List<UserTask>}
|
||||
* @return {@link List<UserTask>}
|
||||
* @since 2024/4/8 15:42
|
||||
**/
|
||||
public static List<UserTask> getChildUserTasks(FlowElement source, List<String> runTaskKeyList,
|
||||
Set<String> passFlows, List<UserTask> userTasks) {
|
||||
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||
userTasks = userTasks == null ? new ArrayList<>() : userTasks;
|
||||
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||
if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
// 连线重复
|
||||
if (passFlows.contains(sequenceFlow.getId())) {
|
||||
continue;
|
||||
}
|
||||
// 添加经过的连线
|
||||
passFlows.add(sequenceFlow.getId());
|
||||
// 用户任务
|
||||
if (sequenceFlow.getTargetFlowElement() instanceof UserTask
|
||||
&& runTaskKeyList.contains(sequenceFlow.getTargetFlowElement().getId())) {
|
||||
userTasks.add((UserTask) sequenceFlow.getTargetFlowElement());
|
||||
continue;
|
||||
}
|
||||
// 子流程,从第一个节点开始获取
|
||||
if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
|
||||
FlowElement flowElement = (FlowElement) ((SubProcess) sequenceFlow.getTargetFlowElement())
|
||||
.getFlowElements().toArray()[0];
|
||||
List<UserTask> tasks = getChildUserTasks(flowElement, runTaskKeyList, passFlows, null);
|
||||
// 找到用户任务,不继续向下找
|
||||
if (!tasks.isEmpty()) {
|
||||
userTasks.addAll(tasks);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 迭代
|
||||
getChildUserTasks(sequenceFlow.getTargetFlowElement(), runTaskKeyList, passFlows, userTasks);
|
||||
}
|
||||
}
|
||||
return userTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上一级节点
|
||||
*
|
||||
* @param source {@link FlowElement}
|
||||
* @param passFlows {@link Set<String>}
|
||||
* @param parentActs {@link List<String>}
|
||||
* @return {@link List<Activity>}
|
||||
* @since 2024/4/8 15:53
|
||||
**/
|
||||
public static List<String> getParentActs(FlowElement source, Set<String> passFlows, List<String> parentActs) {
|
||||
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||
parentActs = parentActs == null ? new ArrayList<>() : parentActs;
|
||||
|
||||
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||
if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
// 连线重复
|
||||
if (passFlows.contains(sequenceFlow.getId())) {
|
||||
continue;
|
||||
}
|
||||
// 添加经过的连线
|
||||
passFlows.add(sequenceFlow.getId());
|
||||
// 添加用户任务、子流程
|
||||
if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
|
||||
parentActs.add(sequenceFlow.getSourceFlowElement().getId());
|
||||
continue;
|
||||
}
|
||||
if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
|
||||
parentActs.add(sequenceFlow.getSourceFlowElement().getId());
|
||||
continue;
|
||||
}
|
||||
// 迭代
|
||||
getParentActs(sequenceFlow.getSourceFlowElement(), passFlows, parentActs);
|
||||
}
|
||||
}
|
||||
return parentActs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一级的用户任务
|
||||
*
|
||||
* @param source {@link FlowElement}
|
||||
* @param hasSequenceFlow {@link Set<String>}
|
||||
* @param userTaskList {@link List<UserTask>}
|
||||
* @return {@link List<UserTask>}
|
||||
* @since 2024/4/8 16:34
|
||||
**/
|
||||
public static List<UserTask> getNextUserTasks(FlowElement source, Set<String> hasSequenceFlow,
|
||||
List<UserTask> userTaskList) {
|
||||
hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
|
||||
userTaskList = Optional.ofNullable(userTaskList).orElse(new ArrayList<>());
|
||||
// 获取出口连线
|
||||
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||
if (null != sequenceFlows) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
|
||||
continue;
|
||||
}
|
||||
// 添加已经走过的连线
|
||||
hasSequenceFlow.add(sequenceFlow.getId());
|
||||
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||
if (targetFlowElement instanceof UserTask) {
|
||||
// 若节点为用户任务,加入到结果列表中
|
||||
userTaskList.add((UserTask) targetFlowElement);
|
||||
} else {
|
||||
// 若节点非用户任务,继续递归查找下一个节点
|
||||
getNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return userTaskList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取元素之后的所有节点
|
||||
*
|
||||
* @param source {@link FlowElement}
|
||||
* @param hasSequenceFlow {@link Set<String>}
|
||||
* @param list {@link List<String>}
|
||||
* @return {@link List<String>}
|
||||
* @since 2024/4/29 16:00
|
||||
**/
|
||||
public static List<String> getAfter(FlowElement source, Set<String> hasSequenceFlow, List<String> list) {
|
||||
hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
|
||||
list = Optional.ofNullable(list).orElse(new ArrayList<>());
|
||||
// 获取出口连线
|
||||
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||
if (null != sequenceFlows) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
|
||||
continue;
|
||||
}
|
||||
// 添加已经走过的连线
|
||||
hasSequenceFlow.add(sequenceFlow.getId());
|
||||
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||
if (targetFlowElement instanceof UserTask) {
|
||||
// 若节点为用户任务,加入到结果列表中
|
||||
list.add(targetFlowElement.getId());
|
||||
} else if (targetFlowElement instanceof EndEvent) {
|
||||
list.add(targetFlowElement.getId());
|
||||
continue;
|
||||
}
|
||||
// 继续递归查找下一个节点
|
||||
getAfter(targetFlowElement, hasSequenceFlow, list);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点的出口连线,若出线的出口是网关,则一并获取网关的出线
|
||||
*
|
||||
* @param source {@link FlowElement}
|
||||
* @return {@link List<SequenceFlow>}
|
||||
* @since 2024/4/9 9:58
|
||||
**/
|
||||
public static List<SequenceFlow> getOutFlowsWithGateway(FlowElement source, List<SequenceFlow> flows) {
|
||||
flows = flows == null ? new ArrayList<>() : flows;
|
||||
// 获取出口连线
|
||||
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||
if (null != sequenceFlows) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
flows.add(sequenceFlow);
|
||||
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||
if (targetFlowElement instanceof UserTask) {
|
||||
continue;
|
||||
}
|
||||
if (targetFlowElement instanceof Gateway) {
|
||||
Gateway gateway = (Gateway) targetFlowElement;
|
||||
List<SequenceFlow> outgoingFlows = gateway.getOutgoingFlows();
|
||||
flows.addAll(outgoingFlows);
|
||||
getOutFlowsWithGateway(gateway, flows);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取出线,上下级关系
|
||||
*
|
||||
* @param source 源
|
||||
* @param flows 结果集合
|
||||
*/
|
||||
public static List<FlowVo> getOutFlows(FlowElement source, List<FlowVo> flows) {
|
||||
flows = flows == null ? new ArrayList<>() : flows;
|
||||
// 获取出口连线
|
||||
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||
if (null != sequenceFlows) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
FlowVo vo = new FlowVo();
|
||||
vo.setKey(sequenceFlow.getId());
|
||||
|
||||
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||
if (targetFlowElement instanceof Gateway) {
|
||||
Gateway gateway = (Gateway) targetFlowElement;
|
||||
List<FlowVo> list = getOutFlows(gateway, null);
|
||||
vo.setChildren(list);
|
||||
}
|
||||
flows.add(vo);
|
||||
}
|
||||
}
|
||||
return flows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取之前的节点
|
||||
*
|
||||
* @param source {@link FlowElement}
|
||||
* @param passFlows {@link Set<String>}
|
||||
* @param keys {@link List<String>}
|
||||
* @return {@link List<String>}
|
||||
* @since 2024/4/9 11:51
|
||||
**/
|
||||
public static List<String> getBefore(FlowElement source, Set<String> passFlows, List<String> keys) {
|
||||
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||
keys = keys == null ? new ArrayList<>() : keys;
|
||||
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||
if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||
// 连线重复
|
||||
if (passFlows.contains(sequenceFlow.getId())) {
|
||||
continue;
|
||||
}
|
||||
// 添加经过的连线
|
||||
passFlows.add(sequenceFlow.getId());
|
||||
// 添加节点Key
|
||||
keys.add(sequenceFlow.getSourceFlowElement().getId());
|
||||
if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
|
||||
continue;
|
||||
}
|
||||
// 迭代
|
||||
getBefore(sequenceFlow.getSourceFlowElement(), passFlows, keys);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取线之后的任务节点
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getTaskKeyAfterFlow(FlowElement source) {
|
||||
if (source instanceof SequenceFlow) {
|
||||
SequenceFlow sequenceFlow = (SequenceFlow) source;
|
||||
FlowElement target = sequenceFlow.getTargetFlowElement();
|
||||
if (target instanceof Gateway) {
|
||||
List<SequenceFlow> outgoingFlows = ((Gateway) target).getOutgoingFlows();
|
||||
if (CollectionUtil.isNotEmpty(outgoingFlows)) {
|
||||
SequenceFlow flow = outgoingFlows.get(0);
|
||||
return getTaskKeyAfterFlow(flow);
|
||||
}
|
||||
}
|
||||
if (target instanceof UserTask) {
|
||||
return target.getId();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user