package jnpf.workflow.flowable.service; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import org.flowable.bpmn.model.BaseElement; import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.SequenceFlow; import org.flowable.bpmn.model.UserTask; import org.flowable.engine.HistoryService; import org.flowable.engine.ManagementService; import org.flowable.engine.RepositoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; 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 cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import jnpf.workflow.common.exception.BizException; import jnpf.workflow.common.exception.ResultCode; import jnpf.workflow.common.model.fo.CompensateFo; import jnpf.workflow.common.model.fo.FlowTargetTaskFo; import jnpf.workflow.common.model.fo.InfoModel; import jnpf.workflow.common.model.fo.InstanceStartFo; import jnpf.workflow.common.model.fo.JumpFo; import jnpf.workflow.common.model.fo.MoveMultiToSingleFo; import jnpf.workflow.common.model.fo.MoveSingleToMultiFo; import jnpf.workflow.common.model.fo.TaskAfterFo; import jnpf.workflow.common.model.fo.TaskBackFo; import jnpf.workflow.common.model.fo.TaskCompleteFo; import jnpf.workflow.common.model.fo.TaskNextFo; import jnpf.workflow.common.model.fo.TaskOutgoingFo; import jnpf.workflow.common.model.fo.TaskPrevFo; import jnpf.workflow.common.model.vo.FlowVo; import jnpf.workflow.common.model.vo.HistoricNodeVo; import jnpf.workflow.common.model.vo.InstanceVo; import jnpf.workflow.common.model.vo.NodeElementVo; import jnpf.workflow.common.model.vo.TaskVo; import jnpf.workflow.common.service.IInstanceService; import jnpf.workflow.common.service.ITaskService; import jnpf.workflow.flowable.cmd.JumpCmd; import jnpf.workflow.flowable.util.FlowableUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j @Service @RequiredArgsConstructor 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 getTask(String instanceId) { List list = taskService.createTaskQuery().processInstanceId(instanceId).list(); List 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 { moveSingleActivityIdToActivityIds(fo.getInstanceId(), fo.getSourceKey(), fo.getTargetKeys()); return true; } catch (Exception e) { log.error(ResultCode.TASK_JUMP_ERROR.getMsg(), e); return false; } } public void moveSingleActivityIdToActivityIds(String processInstanceId, String activityId, List 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 { moveActivityIdsToSingleActivityId(fo.getInstanceId(), fo.getSourceKeys(), fo.getTargetKey()); return true; } catch (Exception e) { log.error(ResultCode.TASK_JUMP_ERROR.getMsg(), e); return false; } } public void moveActivityIdsToSingleActivityId(String processInstanceId, List 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 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 list = FlowableUtil.getPassActs(source, null, null); return list.stream().distinct().collect(Collectors.toList()); } 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 elements = FlowableUtil.getAllElements(process.getFlowElements(), null); FlowElement source = null; if (null != elements && !elements.isEmpty()) { for (FlowElement element : elements) { if (!element.getId().equals(taskDefinitionKey)) { continue; } source = element; } } return source; } @Override public List back(TaskBackFo fo) { String instanceId; String definitionId; Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult(); 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 list = Arrays.asList(split); return back(definitionId, instanceId, list); } return null; } public List back(String definitionId, String instanceId, List targetList) { List currentIds = new ArrayList<>(); for (String targetKey : targetList) { FlowElement target = getFlowElement(definitionId, targetKey); List runTaskList = taskService.createTaskQuery().processInstanceId(instanceId).list(); List runTaskKeyList = runTaskList.stream().map(TaskInfo::getTaskDefinitionKey).collect(Collectors.toList()); List userTaskList = FlowableUtil.getChildUserTasks(target, runTaskKeyList, null, null); List collect = userTaskList.stream().map(BaseElement::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); jump(jumpFo); return currentIds; } @Override public List getPrevUserTask(TaskPrevFo fo) { List list; 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 getNextUserTask(TaskNextFo fo) { List nextUserTasks; FlowElement source; if (StrUtil.isNotBlank(fo.getDeploymentId())) { ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(fo.getDeploymentId()).singleResult(); if (null == definition) { throw new BizException(ResultCode.DEFINITION_NOT_EXIST); } 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); } source = getFlowElement(taskInst.getProcessDefinitionId(), taskInst.getTaskDefinitionKey()); nextUserTasks = FlowableUtil.getNextUserTasks(source, null, null); } List vos = new ArrayList<>(); if (CollectionUtil.isNotEmpty(nextUserTasks)) { for (UserTask userTask : nextUserTasks) { NodeElementVo vo = new NodeElementVo(); vo.setId(userTask.getId()); vo.setName(userTask.getName()); vo.setIncomingList(userTask.getIncomingFlows().stream().map(BaseElement::getId).collect(Collectors.toList())); vo.setOutgoingList(userTask.getOutgoingFlows().stream().map(BaseElement::getId).collect(Collectors.toList())); vos.add(vo); } } return vos; } @Override public List getTaskKeyAfterFlow(FlowTargetTaskFo fo) { ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(fo.getDeploymentId()).singleResult(); if (null == definition) { throw new BizException(ResultCode.DEFINITION_NOT_EXIST); } List 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 nextUserTasks = FlowableUtil.getNextUserTasks(source, null, null); List nextUserTaskKeys = nextUserTasks.stream().map(BaseElement::getId).collect(Collectors.toList()); List activateTasks = taskService.createTaskQuery().processInstanceId(taskInst.getProcessInstanceId()).list(); List currentIds = new ArrayList<>(); for (Task task : activateTasks) { if (!CollUtil.contains(nextUserTaskKeys, task.getTaskDefinitionKey())) { continue; } currentIds.add(task.getTaskDefinitionKey()); } moveActivityIdsToSingleActivityId(taskInst.getProcessInstanceId(), currentIds, taskInst.getTaskDefinitionKey()); return true; } } return false; } @Override public List 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 getOutgoingFlows(definition.getId(), fo.getTaskKey()); } Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult(); if (null == task) { throw new BizException(ResultCode.TASK_NOT_EXIST); } return getOutgoingFlows(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); } public List getOutgoingFlows(String processDefinitionId, String taskDefinitionKey) { FlowElement source = getFlowElement(processDefinitionId, taskDefinitionKey); List flows = new ArrayList<>(); flows = FlowableUtil.getOutFlowsWithGateway(source, flows); List list = new ArrayList<>(); if (!flows.isEmpty()) { for (SequenceFlow flow : flows) { list.add(flow.getId()); } } return list.stream().distinct().collect(Collectors.toList()); } @Override public List 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 getOutgoing(definition.getId(), fo.getTaskKey()); } Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult(); if (null == task) { throw new BizException(ResultCode.TASK_NOT_EXIST); } return getOutgoing(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); } public List getOutgoing(String processDefinitionId, String taskDefinitionKey) { FlowElement source = getFlowElement(processDefinitionId, taskDefinitionKey); return FlowableUtil.getOutFlows(source, null); } @Override public List getKeysOfFinished(String instanceId) { ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult(); if (null == instance) { throw new BizException(ResultCode.INSTANCE_NOT_EXIST); } List keysOfBefore = getKeysOfBefore(instance); List list = historyService.createHistoricActivityInstanceQuery() .processInstanceId(instanceId).finished().list(); if (CollectionUtil.isNotEmpty(list)) { List keysOfFinished = list.stream() .filter(e -> !"sequenceFlow".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 getKeysOfBefore(ProcessInstance instance) { List res = new ArrayList<>(); List taskList = taskService.createTaskQuery().processInstanceId(instance.getId()).list(); if (CollectionUtil.isNotEmpty(taskList)) { List keys = taskList.stream().map(TaskInfo::getTaskDefinitionKey).collect(Collectors.toList()); for (String key : keys) { FlowElement source = getFlowElement(instance.getProcessDefinitionId(), key); List list = FlowableUtil.getBefore(source, null, null); res.addAll(list); } } return res.stream().distinct().collect(Collectors.toList()); } @Override public List getIncomingFlows(String taskId) { HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult(); if (null != taskInst) { FlowElement source = getFlowElement(taskInst.getProcessDefinitionId(), taskInst.getTaskDefinitionKey()); List flows = FlowableUtil.getElementIncomingFlows(source); return flows.stream().map(BaseElement::getId).collect(Collectors.toList()); } return null; } @Override public List getToBePass(String instanceId) { List list = new ArrayList<>(); List currentList = taskService.createTaskQuery().processInstanceId(instanceId).list(); if (CollectionUtil.isNotEmpty(currentList)) { List collect = currentList.stream().map(TaskInfo::getTaskDefinitionKey).collect(Collectors.toList()); for (Task task : currentList) { FlowElement source = getFlowElement(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); List 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 getAfter(TaskAfterFo fo) { String deploymentId = fo.getDeploymentId(); List taskKeys = fo.getTaskKeys(); List 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 after = FlowableUtil.getAfter(source, null, null); list.addAll(after); } return list.stream().distinct().collect(Collectors.toList()); } @Override public List 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 variables = new HashMap<>(); List 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 sourceList = fo.getSource().stream().sorted().collect(Collectors.toList()); List taskVoList = getTask(instanceId); List currentList = taskVoList.stream().map(TaskVo::getTaskKey).sorted().collect(Collectors.toList()); List createList = sourceList.stream().filter(e -> !currentList.contains(e)).collect(Collectors.toList()); List deleteList = currentList.stream().filter(e -> !sourceList.contains(e)).collect(Collectors.toList()); JumpFo jumpFo = new JumpFo(); jumpFo.setInstanceId(instanceId); jumpFo.setSource(deleteList); jumpFo.setTarget(createList); jump(jumpFo); List vos = getTask(instanceId); if (null != instance) { vos.forEach(e -> e.setInstanceId(null)); } return vos; } @Override public List getHistoric(String instanceId) { Set set = new HashSet<>(); set.add("userTask"); set.add("startEvent"); List vos = getHistoricVos(instanceId, set); return vos.stream().sorted(Comparator.comparing(HistoricNodeVo::getStartTime)).collect(Collectors.toList()); } @Override public List getHistoricEnd(String instanceId) { List list = new ArrayList<>(); List vos = getHistoricVos(instanceId, null); if (CollectionUtil.isNotEmpty(vos)) { list = vos.stream().map(HistoricNodeVo::getCode).distinct().collect(Collectors.toList()); } return list; } public List getHistoricVos(String instanceId, Set set) { List vos = new ArrayList<>(); if (CollectionUtil.isEmpty(set)) { set = new HashSet<>(); set.add("endEvent"); } List 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 outgoingFlows = FlowableUtil.getElementOutgoingFlows(source); vo.setOutgoingList(outgoingFlows.stream().map(BaseElement::getId).collect(Collectors.toList())); List incomingFlows = FlowableUtil.getElementIncomingFlows(source); vo.setIncomingList(incomingFlows.stream().map(BaseElement::getId).collect(Collectors.toList())); } return vo; } }