节点跳转
参考:https://blog.csdn.net/qh870754310/article/details/99692923
可让工作流不按照流程图流程,进行任务节点的转换
Flowable内置了相关的API,跳转时需要当前节点的TaskDefinitionKey和要跳转到节点的TaskDefinitionKey
/**
* 单节点跳转单节点
*/
public void jumpTaskNodeOneToOne(String processInstanceId, String fromNodeId, String toNodeId) {
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId)
.moveActivityIdTo(fromNodeId, toNodeId).changeState();
}
/**
* 多节点跳转单节点(并行节点跳单节点)
*/
public void jumpTaskNodeMoreToOne(String processInstanceId, List<String> fromNodeIds, String toNodeId) {
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId)
.moveActivityIdsToSingleActivityId(fromNodeIds, toNodeId).changeState();
}
/**
* 单节点跳多节点(单节点跳并行节点)
*/
public void jumpTaskNodeOneToMore(String processInstanceId, String fromNodeId, List<String> toNodeIds) {
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId)
.moveSingleActivityIdToActivityIds(fromNodeId, toNodeIds).changeState();
}
获取流程中所有节点及连线
通过流程配置文件
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(lastVersionBpmnXml.getBpnmXml());
BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
InputStreamSource inputStreamProvider = new InputStreamSource(byteArrayInputStream);
BpmnModel bpmnModel = bpmnXMLConverter.convertToBpmnModel(inputStreamProvider, false, false);
Process mainProcess = bpmnModel.getMainProcess();
Collection<FlowElement> flowElements = mainProcess.getFlowElements();
通过流程定义ID
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
Collection<FlowElement> flowElements = mainProcess.getFlowElements();
用户任务节点转多实例任务节点
创建UserTask转换为MultiTask的Command类
/**
* 将当前userTask变为多实例
*/
public class ChangeUserTaskToMulitInProcessInstanceCmd extends AbstractDynamicInjectionCmd implements Command<Void> {
protected String processInstanceId;
protected DynamicUserTaskBuilder dynamicUserTaskBuilder;
protected FlowElement currentFlowElement;
public ChangeUserTaskToMulitInProcessInstanceCmd(String processInstanceId,
DynamicUserTaskBuilder dynamicUserTaskBuilder, FlowElement currentFlowElement) {
this.processInstanceId = processInstanceId;
this.dynamicUserTaskBuilder = dynamicUserTaskBuilder;
this.currentFlowElement = currentFlowElement;
}
@Override
public Void execute(CommandContext commandContext) {
createDerivedProcessDefinitionForProcessInstance(commandContext, processInstanceId);
return null;
}
@Override
protected void updateBpmnProcess(CommandContext commandContext, Process process, BpmnModel bpmnModel,
ProcessDefinitionEntity originalProcessDefinitionEntity, DeploymentEntity newDeploymentEntity) {
List<StartEvent> startEvents = process.findFlowElementsOfType(StartEvent.class);
StartEvent initialStartEvent = null;
for (StartEvent startEvent : startEvents) {
if (startEvent.getEventDefinitions().size() == 0) {
initialStartEvent = startEvent;
break;
} else if (initialStartEvent == null) {
initialStartEvent = startEvent;
}
}
if (currentFlowElement != null) {
// BeanUtils.copyProperties(currentFlowElement, userTask);
UserTask userTask = (UserTask) process.getFlowElement(currentFlowElement.getId());
userTask.setTaskListeners(fillMultiTaskFlowableListeners());
userTask.setName(dynamicUserTaskBuilder.getName());
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();
// 配置节点人员办理顺序 串行:true 并行:false.
multiInstanceLoopCharacteristics.setSequential(false);
// 配置会签集合变量名称.
multiInstanceLoopCharacteristics.setInputDataItem("${assigneeList}");
// 配置会签集合遍历名称.
multiInstanceLoopCharacteristics.setElementVariable("assignee");
// 将下一节点元素转换为任务节点对象.
// 设置下一节点处理人表达式 引用会签条件activiti:elementVariable="assignee".
userTask.setAssignee("${assignee}");
// 下一任务节点设置会签循环特征.
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
multiInstanceLoopCharacteristics
.setCompletionCondition("${multiOneVoteVetoCompleteTask.accessCondition(execution)}");
// 获取流程引擎配置实现类.
ProcessEngineConfigurationImpl processEngineConfiguration = (ProcessEngineConfigurationImpl) ProcessEngines
.getDefaultProcessEngine().getProcessEngineConfiguration();
// 创建新的任务实例.
UserTaskActivityBehavior userTaskActivityBehavior =
processEngineConfiguration.getActivityBehaviorFactory().createUserTaskActivityBehavior(userTask);
// 创建BPMN 2.0规范中描述的多实例功能.
ParallelMultiInstanceBehavior behavior =
new ParallelMultiInstanceBehavior(userTask, userTaskActivityBehavior);
// 设置下一节点多实例行为.
userTask.setBehavior(behavior);
// 设置多实例元素变量.
behavior.setCollectionElementVariable("assignee");
// 注入表达式.
ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();
// 设置多实例集合表达式.
behavior.setCollectionExpression(expressionManager.createExpression("${assigneeList}"));
behavior.setCompletionCondition("${multiOneVoteVetoCompleteTask.accessCondition(execution)}");
// 自动布局
// new BpmnAutoLayout(bpmnModel).execute();
} else {
// 官方API中的代码,增加并行网关,新增的节点执行后结束流程
ParallelGateway parallelGateway = new ParallelGateway();
parallelGateway.setId(dynamicUserTaskBuilder.nextForkGatewayId(process.getFlowElementMap()));
process.addFlowElement(parallelGateway);
UserTask userTask = new UserTask();
if (dynamicUserTaskBuilder.getId() != null) {
userTask.setId(dynamicUserTaskBuilder.getId());
} else {
userTask.setId(dynamicUserTaskBuilder.nextTaskId(process.getFlowElementMap()));
}
dynamicUserTaskBuilder.setDynamicTaskId(userTask.getId());
userTask.setName(dynamicUserTaskBuilder.getName());
userTask.setAssignee(dynamicUserTaskBuilder.getAssignee());
process.addFlowElement(userTask);
EndEvent endEvent = new EndEvent();
endEvent.setId(dynamicUserTaskBuilder.nextEndEventId(process.getFlowElementMap()));
process.addFlowElement(endEvent);
SequenceFlow flowToUserTask = new SequenceFlow(parallelGateway.getId(), userTask.getId());
flowToUserTask.setId(dynamicUserTaskBuilder.nextFlowId(process.getFlowElementMap()));
process.addFlowElement(flowToUserTask);
SequenceFlow flowFromUserTask = new SequenceFlow(userTask.getId(), endEvent.getId());
flowFromUserTask.setId(dynamicUserTaskBuilder.nextFlowId(process.getFlowElementMap()));
process.addFlowElement(flowFromUserTask);
SequenceFlow initialFlow = initialStartEvent.getOutgoingFlows().get(0);
initialFlow.setSourceRef(parallelGateway.getId());
SequenceFlow flowFromStart = new SequenceFlow(initialStartEvent.getId(), parallelGateway.getId());
flowFromStart.setId(dynamicUserTaskBuilder.nextFlowId(process.getFlowElementMap()));
process.addFlowElement(flowFromStart);
// 跳整节点的布局
GraphicInfo elementGraphicInfo = bpmnModel.getGraphicInfo(initialStartEvent.getId());
if (elementGraphicInfo != null) {
double yDiff = 0;
double xDiff = 80;
if (elementGraphicInfo.getY() < 173) {
yDiff = 173 - elementGraphicInfo.getY();
elementGraphicInfo.setY(173);
}
Map<String, GraphicInfo> locationMap = bpmnModel.getLocationMap();
for (String locationId : locationMap.keySet()) {
if (initialStartEvent.getId().equals(locationId)) {
continue;
}
GraphicInfo locationGraphicInfo = locationMap.get(locationId);
locationGraphicInfo.setX(locationGraphicInfo.getX() + xDiff);
locationGraphicInfo.setY(locationGraphicInfo.getY() + yDiff);
}
Map<String, List<GraphicInfo>> flowLocationMap = bpmnModel.getFlowLocationMap();
for (String flowId : flowLocationMap.keySet()) {
if (flowFromStart.getId().equals(flowId)) {
continue;
}
List<GraphicInfo> flowGraphicInfoList = flowLocationMap.get(flowId);
for (GraphicInfo flowGraphicInfo : flowGraphicInfoList) {
flowGraphicInfo.setX(flowGraphicInfo.getX() + xDiff);
flowGraphicInfo.setY(flowGraphicInfo.getY() + yDiff);
}
}
GraphicInfo forkGraphicInfo =
new GraphicInfo(elementGraphicInfo.getX() + 75, elementGraphicInfo.getY() - 5, 40, 40);
bpmnModel.addGraphicInfo(parallelGateway.getId(), forkGraphicInfo);
bpmnModel.addFlowGraphicInfoList(flowFromStart.getId(),
createWayPoints(elementGraphicInfo.getX() + 30, elementGraphicInfo.getY() + 15,
elementGraphicInfo.getX() + 75, elementGraphicInfo.getY() + 15));
GraphicInfo newTaskGraphicInfo =
new GraphicInfo(elementGraphicInfo.getX() + 185, elementGraphicInfo.getY() - 163, 80, 100);
bpmnModel.addGraphicInfo(userTask.getId(), newTaskGraphicInfo);
bpmnModel.addFlowGraphicInfoList(flowToUserTask.getId(),
createWayPoints(elementGraphicInfo.getX() + 95, elementGraphicInfo.getY() - 5,
elementGraphicInfo.getX() + 95, elementGraphicInfo.getY() - 123,
elementGraphicInfo.getX() + 185, elementGraphicInfo.getY() - 123));
GraphicInfo endGraphicInfo =
new GraphicInfo(elementGraphicInfo.getX() + 335, elementGraphicInfo.getY() - 137, 28, 28);
bpmnModel.addGraphicInfo(endEvent.getId(), endGraphicInfo);
bpmnModel.addFlowGraphicInfoList(flowFromUserTask.getId(),
createWayPoints(elementGraphicInfo.getX() + 285, elementGraphicInfo.getY() - 123,
elementGraphicInfo.getX() + 335, elementGraphicInfo.getY() - 123));
}
}
BaseDynamicSubProcessInjectUtil.processFlowElements(commandContext, process, bpmnModel,
originalProcessDefinitionEntity, newDeploymentEntity);
}
private List<FlowableListener> fillMultiTaskFlowableListeners() {
List<FlowableListener> list = new ArrayList<>();
FlowableListener flowableListener = new FlowableListener();
flowableListener.setEvent("complete");
flowableListener.setImplementationType("expression");
flowableListener.setImplementation("${afterMultiInstanceSubCompleteListener.notify(task)}");
list.add(flowableListener);
flowableListener = new FlowableListener();
flowableListener.setEvent("create");
flowableListener.setImplementationType("expression");
flowableListener.setImplementation("${beforeMultiUserTaskListener.notify(task)}");
list.add(flowableListener);
return list;
}
@Override
protected void updateExecutions(CommandContext commandContext, ProcessDefinitionEntity processDefinitionEntity,
ExecutionEntity processInstance, List<ExecutionEntity> childExecutions) {
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
List<ExecutionEntity> oldExecution =
executionEntityManager.findChildExecutionsByProcessInstanceId(processInstance.getProcessInstanceId());
ExecutionEntity execution = executionEntityManager.createChildExecution(processInstance);
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionEntity.getId());
org.flowable.task.service.TaskService taskService = CommandContextUtil.getTaskService(commandContext);
List<TaskEntity> taskEntities = taskService.findTasksByProcessInstanceId(processInstanceId);
// 删除当前活动任务
for (TaskEntity taskEntity : taskEntities) {
taskEntity.getIdentityLinks().stream().forEach(identityLinkEntity -> {
if (identityLinkEntity.isGroup()) {
taskEntity.deleteGroupIdentityLink(identityLinkEntity.getGroupId(), "candidate");
} else {
taskEntity.deleteUserIdentityLink(identityLinkEntity.getUserId(), "participant");
}
});
if (taskEntity.getTaskDefinitionKey().equals(currentFlowElement.getId())) {
taskService.deleteTask(taskEntity, false);
}
}
// 设置活动后的节点
// UserTask userTask = (UserTask)
// bpmnModel.getProcessById(processDefinitionEntity.getKey()).getFlowElement(dynamicUserTaskBuilder.getId());
UserTask userTask = (UserTask) bpmnModel.getProcessById(processDefinitionEntity.getKey())
.getFlowElement(currentFlowElement.getId());
execution.setCurrentFlowElement(userTask);
Context.getAgenda().planContinueProcessOperation(execution);
}
@Override
protected ProcessDefinitionEntity deployDerivedDeploymentEntity(CommandContext commandContext,
DeploymentEntity deploymentEntity, ProcessDefinitionEntity originalProcessDefinitionEntity) {
Map<String, Object> deploymentSettings = new HashMap<>();
deploymentSettings.put(DeploymentSettings.IS_DERIVED_DEPLOYMENT, true);
deploymentSettings.put(DeploymentSettings.DERIVED_PROCESS_DEFINITION_ID, originalProcessDefinitionEntity.getId());
deploymentSettings.put(DeploymentSettings.IS_PROCESS_VALIDATION_ENABLED,false);
deploymentSettings.put(DeploymentSettings.IS_BPMN20_XSD_VALIDATION_ENABLED,false);
if (originalProcessDefinitionEntity.getDerivedFromRoot() != null) {
deploymentSettings.put(DeploymentSettings.DERIVED_PROCESS_DEFINITION_ROOT_ID, originalProcessDefinitionEntity.getDerivedFromRoot());
} else {
deploymentSettings.put(DeploymentSettings.DERIVED_PROCESS_DEFINITION_ROOT_ID, originalProcessDefinitionEntity.getId());
}
deploymentEntity.setNew(true);
List<EngineDeployer> deployers = CommandContextUtil.getProcessEngineConfiguration(commandContext).getDeploymentManager().getDeployers();
for (EngineDeployer engineDeployer : deployers) {
engineDeployer.deploy(deploymentEntity, deploymentSettings);
}
return deploymentEntity.getDeployedArtifacts(ProcessDefinitionEntity.class).get(0);
}
}
调用该类
private String doUserTaskAddToMulti(Task task, String processInstanceId) {
String dynamicUserId = "ADD_TASK_" + UUID.randomUUID().toString().replaceAll("-", "");
DynamicUserTaskBuilder dynamicUserTaskBuilder = new DynamicUserTaskBuilder();
dynamicUserTaskBuilder.setId(dynamicUserId);
dynamicUserTaskBuilder.setName(task.getName() + WorkflowConst.ADD_REVIEWER_SUFFIX);
dynamicUserTaskBuilder.setAssignee(task.getAssignee());
String processDefinitionId = task.getProcessDefinitionId();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
Process process = bpmnModel.getProcesses().get(0);
try {
processEngine.getManagementService().executeCommand(new ChangeUserTaskToMulitInProcessInstanceCmd(
processInstanceId, dynamicUserTaskBuilder, process.getFlowElement(task.getTaskDefinitionKey())));
} catch (Exception e) {
log.error(WorkflowResultCode.WORKFLOW_ADD_TASK_FAIL.getMessage(), e);
throw new ResultCodeException(WorkflowResultCode.WORKFLOW_ADD_TASK_FAIL, e);
}
return dynamicUserId;
}
调用之后,流程实例ID、流程定义ID、任务ID、流程部署ID均会产生变化,因在远UserTask上进行改造,故TaskDefinitionKey不变。