10.任务节点/TaskController
1.查询所有任务
查询所有的任务节点,主要调用historyService API提供的方法,详细逻辑见注释。
@GetMapping(value = "/list")
public Result list(TaskQueryVo taskQueryVo) {
// 使用historyServiceAPI构建可输入条件的查询工厂
HistoricTaskInstanceQuery query = createHistoricTaskInstanceQuery(taskQueryVo);
//执行API的查询与排序
FlowablePage page = this.pageList(taskQueryVo, query, TaskListWrapper.class, allowedSortProperties,
HistoricTaskInstanceQueryProperty.START);
return Result.ok(page);
}
2.已办任务
我的已办任务列表,主要调用historyService API提供的方法(同上),并加入查询条件,详细逻辑见注释。
@GetMapping(value = "/listDone")
public Result listDone(TaskQueryVo taskQueryVo) {
//根据historyService api创建查询工厂
HistoricTaskInstanceQuery query = createHistoricTaskInstanceQuery(taskQueryVo);
// 组装参数 加入查询条件,条件为已经完成/自己提交的/自己审批的
query.finished().or().taskAssignee(SecurityUtils.getUserId())
.taskOwner(SecurityUtils.getUserId()).endOr();
//执行API的查询与排序
FlowablePage page = this.pageList(taskQueryVo, query, TaskListWrapper.class, allowedSortProperties,
HistoricTaskInstanceQueryProperty.START);
return Result.ok(page);
}
3.我的待办
我的待办任务列表,主要调用historyService API提供的方法(同上),并加入查询条件,详细逻辑见注释。
@GetMapping(value = "/listTodo")
public Result listTodo(TaskQueryVo taskQueryVo) {
String userId = SecurityUtils.getUserId();
// 根据historyService api创建查询工厂
TaskQuery query = createTaskQuery(taskQueryVo);
// 拼写参数 组装查询条件 条件为待办 且审批人为自己
query.taskCategory(FlowableConstant.CATEGORY_TODO);
query.or().taskCandidateOrAssigned(userId).taskOwner(userId).endOr();
// 调用API方法查询
FlowablePage page = this.pageList(taskQueryVo, query, TaskTodoListWrapper.class, allowedSortProperties,
TaskQueryProperty.CREATE_TIME);
return Result.ok(page);
}
4.查询任务详情
我的待办任务列表,查询任务节点信息,并拼装所有详细信息返回,详细逻辑见注释。
@GetMapping(value = "/queryById")
public Result queryById(@RequestParam String taskId) {
//调用service方法
TaskResponse task = flowableTaskService.getTask(taskId);
return Result.ok(task);
}
@Override
public TaskResponse getTask(String taskId) {
String userId = SecurityUtils.getUserId();
//查询当前任务信息,并验证是否有查看权限
HistoricTaskInstance taskHis = permissionService.validateReadPermissionOnTask(taskId, userId, true, true);
TaskResponse rep = null;
ProcessDefinition processDefinition = null;
String formKey = null;
Object renderedTaskForm = null;
HistoricTaskInstance parentTask = null;
//验证流程定义
if (StringUtils.isNotEmpty(taskHis.getProcessDefinitionId())) {
//查询流程定义信息
processDefinition = repositoryService.getProcessDefinition(taskHis.getProcessDefinitionId());
//挂载的表单信息
formKey = formService.getTaskFormKey(processDefinition.getId(), taskHis.getTaskDefinitionKey());
if (taskHis.getEndTime() == null && formKey != null && formKey.length() > 0) {
//获取表单json
renderedTaskForm = formService.getRenderedTaskForm(taskId);
}
}
if (StringUtils.isNotEmpty(taskHis.getParentTaskId())) {
parentTask =
historyService.createHistoricTaskInstanceQuery().taskId(taskHis.getParentTaskId()).singleResult();
}
rep = new TaskResponse(taskHis, processDefinition, parentTask, null);
rep.setFormKey(formKey);
rep.setRenderedTaskForm(renderedTaskForm);
//补全身份信息
fillPermissionInformation(rep, taskHis, userId);
// 补全审批人信息
populateAssignee(taskHis, rep);
rep.setInvolvedPeople(getInvolvedUsers(taskId));
Task task = null;
if (taskHis.getEndTime() == null) {
task = taskService.createTaskQuery().taskId(taskId).singleResult();
rep.setSuspended(task.isSuspended());
rep.setDelegationState(task.getDelegationState());
}
//将用有人加入实体
rep.setOwnerName(this.getUserName(taskHis.getOwner()));
//将审批人加入实体
rep.setAssigneeName(this.getUserName(taskHis.getAssignee()));
return rep;
}
5.转办任务
在审批时的转办业务,就是在当前审批加入一条过程意见,并重新设置新的审批人。详细逻辑见注释。
@PutMapping(value = "/assign")
public Result assign(@RequestBody TaskRequest taskRequest) {
//调用service方法
flowableTaskService.assignTask(taskRequest);
return Result.ok();
}
public void assignTask(TaskRequest taskRequest) {
String taskId = taskRequest.getTaskId();
String assignee = taskRequest.getUserId();
String userId = SecurityUtils.getUserId();
//获取任务信息
Task task = permissionService.validateAssignPermissionOnTask(taskId, userId, assignee);
//添加任务过程意见
this.addComment(taskId, task.getProcessInstanceId(), userId, CommentTypeEnum.ZB, taskRequest.getMessage());
//重新设置审批人
taskService.setAssignee(task.getId(), assignee);
}
6.委派任务
在审批过程中的委派业务,同上文,只不过需要调用提供的API,详细逻辑见注释。
@PutMapping(value = "/delegate")
public Result delegate(@RequestBody TaskRequest taskRequest) {
//调用service方法
flowableTaskService.delegateTask(taskRequest);
return Result.ok();
}
public void delegateTask(TaskRequest taskRequest) {
String taskId = taskRequest.getTaskId();
String delegater = taskRequest.getUserId();
String userId =SecurityUtils.getUserId();
//获取任务节点信息
Task task = permissionService.validateDelegatePermissionOnTask(taskId, userId, delegater);
//添加一条过程意见
this.addComment(taskId, task.getProcessInstanceId(), userId, CommentTypeEnum.WP, taskRequest.getMessage());
//调用API,委派人审批后,当前人需要再次审批
taskService.delegateTask(task.getId(), delegater);
}
7.认领任务
如类似组审批的情况,下一个节点可能很多人都能够审批该任务节点,这时候需要这些人中某一个认领该任务,认领后其他人在待办中不能在次查询到。API提供了认领的方法,详细逻辑见注释。
@PutMapping(value = "/claim")
public Result claim(@RequestBody TaskRequest taskRequest) {
// 调用service提供方法
flowableTaskService.claimTask(taskRequest);
return Result.ok();
}
public void claimTask(TaskRequest taskRequest) {
String taskId = taskRequest.getTaskId();
String userId = SecurityUtils.getUserId();
//获取任务节点信息
TaskInfo task = permissionService.validateReadPermissionOnTask2(taskId, userId, false, false);
if (task.getAssignee() != null && task.getAssignee().length() > 0) {
throw new FlowableNoPermissionException("User does not have permission");
}
//添加过程意见
this.addComment(taskId, task.getProcessInstanceId(), userId, CommentTypeEnum.RL, taskRequest.getMessage());
//认领任务(及指定审批人只能为当前任)个人认为是设置审批人为具体用户
taskService.claim(taskId, userId);
}
8.取消认领
与上文相反,回去初始状态,主要调用API方法,详细逻辑见注释。
@PutMapping(value = "/unclaim")
public Result unclaim(@RequestBody TaskRequest taskRequest) {
//调用service方法
flowableTaskService.unclaimTask(taskRequest);
return Result.ok();
}
public void unclaimTask(TaskRequest taskRequest) {
String taskId = taskRequest.getTaskId();
String userId = SecurityUtils.getUserId();
TaskInfo task = this.getTaskNotNull(taskId);
if (!userId.equals(task.getAssignee())) {
throw new FlowableNoPermissionException("User does not have permission");
}
if (FlowableConstant.CATEGORY_TO_READ.equals(task.getCategory())) {
throw new FlowableNoPermissionException("User cannot unclaim the read task");
}
if (FlowableConstant.INITIATOR.equals(task.getTaskDefinitionKey())) {
throw new FlowableNoPermissionException("Initiator cannot unclaim the task");
}
//添加流程意见
this.addComment(taskId, task.getProcessInstanceId(), userId, CommentTypeEnum.QXRL, taskRequest.getMessage());
//调用API
taskService.unclaim(taskId);
// 判断是否是协办取消认领
if (permissionService.isTaskPending((Task)task)) {
//调用API
taskService.resolveTask(taskId, null);
}
}
9.完成任务
提交任务,主要为调用API的complete()方法,在方法上放为拼接api需要的参数,详细逻辑见注释。
@PutMapping(value = "/complete")
public Result complete(@RequestBody TaskRequest taskRequest) {
//调用service方法
flowableTaskService.completeTask(taskRequest);
return Result.ok();
}
public void completeTask(TaskRequest taskRequest) {
String taskId = taskRequest.getTaskId();
String currUserId = SecurityUtils.getUserId()
Task task = getTaskNotNull(taskId);
//判断用户是否有权限审批
if (!permissionService.isTaskOwnerOrAssignee(currUserId, task)) {
if (StringUtils.isEmpty(task.getScopeType())
&& !permissionService.validateIfUserIsInitiatorAndCanCompleteTask(currUserId, task)) {
throw new FlowableNoPermissionException("User does not have permission");
}
}
Map<String, Object> completeVariables = null;
//验证当前节点是否挂载了审批时的表单
if (taskRequest.getValues() != null && !taskRequest.getValues().isEmpty()) {
//获取挂载表单的输入值
completeVariables = taskRequest.getValues();
// 允许任务表单修改流程表单场景 begin
// 与前端约定:流程表单变量名为 processInstanceFormData,且只有流程表单startFormKey=taskFormKey时才允许修改该变量的值,防止恶意节点修改流程表单内容
if (completeVariables.containsKey(FlowableConstant.PROCESS_INSTANCE_FORM_DATA)) {
String startFormKey = formService.getStartFormKey(task.getProcessDefinitionId());
String taskFormKey =
formService.getTaskFormKey(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
boolean modifyProcessInstanceFormData = CommonFlowableUtil.isNotEmptyStr(startFormKey)
&& CommonFlowableUtil.isNotEmptyStr(taskFormKey) && startFormKey.equals(taskFormKey);
if (!modifyProcessInstanceFormData) {
throw new FlowableNoPermissionException("User does not have permission");
}
}
// 允许任务表单修改流程表单场景 end
// 非会签用户节点,默认设置流程变量 __taskDefinitionKey__=currUserId,用于存储该节点执行人,且以最近的执行人为准
UserTask userTask = (UserTask)FlowableUtils.getFlowElement(repositoryService, task.getProcessDefinitionId(),
task.getTaskDefinitionKey());
if (userTask != null && !userTask.hasMultiInstanceLoopCharacteristics()) {
completeVariables.put("__" + task.getTaskDefinitionKey() + "__", currUserId);
}
} else {
// 非会签用户节点,默认设置流程变量 __taskDefinitionKey__=currUserId,用于存储该节点执行人,且以最近的执行人为准
UserTask userTask = (UserTask)FlowableUtils.getFlowElement(repositoryService, task.getProcessDefinitionId(),
task.getTaskDefinitionKey());
if (userTask != null && !userTask.hasMultiInstanceLoopCharacteristics()) {
completeVariables = new HashMap<>(1);
completeVariables.put("__" + task.getTaskDefinitionKey() + "__", currUserId);
}
}
//添加流程意见
this.addComment(taskId, task.getProcessInstanceId(), currUserId,
FlowableConstant.INITIATOR.equals(task.getTaskDefinitionKey()) ? CommentTypeEnum.CXTJ : CommentTypeEnum.WC,
taskRequest.getMessage());
// 处理抄送
if (CommonFlowableUtil.isNotEmptyObject(taskRequest.getCcToVos())) {
managementService.executeCommand(new AddCcIdentityLinkCmd(task.getProcessInstanceId(), task.getId(),
currUserId, taskRequest.getCcToVos()));
}
//添加审批人
if (task.getAssignee() == null || !task.getAssignee().equals(currUserId)) {
taskService.setAssignee(taskId, currUserId);
}
// 判断是否是协办完成还是正常流转
if (permissionService.isTaskPending(task)) {
taskService.resolveTask(taskId, completeVariables);
// 如果当前执行人是任务所有人,直接完成任务
if (currUserId.equals(task.getOwner())) {
//调用api
taskService.complete(taskId, completeVariables);
}
} else {
//调用api
taskService.complete(taskId, completeVariables);
}
}
1.处理抄送人
在浏览过程可以看到有抄送人处理,调用了自定义的类。主要是拼装抄送人的详细信息,并调用提供的API方法。
public Void execute(CommandContext commandContext) {
// 获取流程信息
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
ExecutionEntity processInstance = executionEntityManager.findById(processInstanceId);
if (processInstance == null) {
throw new FlowableObjectNotFoundException("Cannot find process instance with id " + processInstanceId,
ExecutionEntity.class);
}
// 获取人员具体信息
for (CcToVo ccTo : ccToVos) {
IdentityLinkUtil.createProcessInstanceIdentityLink(processInstance, ccTo.getUserId(), null,
FlowableConstant.CC);
}
this.createCcComment(commandContext);
return null;
}
protected void createCcComment(CommandContext commandContext) {
CommentEntityManager commentEntityManager = CommandContextUtil.getCommentEntityManager(commandContext);
CommentEntity comment = (CommentEntity)commentEntityManager.create();
// 拼装抄送人信息
comment.setProcessInstanceId(processInstanceId);
comment.setUserId(userId);
comment.setType(FlowableConstant.CC);
comment.setTime(CommandContextUtil.getProcessEngineConfiguration(commandContext).getClock().getCurrentTime());
comment.setTaskId(taskId);
comment.setAction("AddCcTo");
String ccToStr = StringUtils.arrayToCommaDelimitedString((Object[])ccToVos);
comment.setMessage(ccToStr);
comment.setFullMessage(ccToStr);
// 调用api
commentEntityManager.insert(comment);
}
10.终止流程
只有当前人和管理员能够终止流程(如表单填写错误等),拼装完流程信息后,直接调用API更改流程状态。详细逻辑见注释。
@PutMapping(value = "/stopProcessInstance")
public Result stopProcessInstance(@RequestBody TaskRequest taskRequest) {
// 调用service提供方法
flowableTaskService.stopProcessInstance(taskRequest);
return Result.ok();
}
public void stopProcessInstance(TaskRequest taskRequest) {
String taskId = taskRequest.getTaskId();
String userId = SecurityUtils.getUserId();
//验证是否有权限结束流程
ProcessInstance processInstance = permissionService.validateStopProcessInstancePermissionOnTask(taskId, userId);
//获取bpmn的对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
if (bpmnModel != null) {
Process process = bpmnModel.getMainProcess();
List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
//查询结束节点的个数
if (endNodes != null && endNodes.size() > 0) {
//添加过程意见
this.addComment(taskId, processInstance.getProcessInstanceId(), userId, CommentTypeEnum.ZZ,
taskRequest.getMessage());
//获取第一个结束节点id
String endId = endNodes.get(0).getId();
//获取流程定义信息
List<Execution> executions =
runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
List<String> executionIds = new ArrayList<>();
executions.forEach(execution -> executionIds.add(execution.getId()));
//调用api更改状态为未激活
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId)
.changeState();
}
}
}
11.发起流程-查询表单信息
发起流程时,渲染需要填写的表单信息。主要为调用API,详细逻辑见注释。
@GetMapping(value = "/renderedTaskForm")
public ResultrenderedTaskForm(@RequestParam String taskId) {
// 验证用户
permissionService.validateReadPermissionOnTask2(taskId, SecurityUtils.getUserId(), true,
true);
// 执行查询 调用api
Object renderedTaskForm = formService.getRenderedTaskForm(taskId);
return Result.ok(renderedTaskForm);
}
12.执行审批弹窗页面
主要输出为申请人表单与需要填写的审批表单信息。使用API查询信息,并拼装返回。详细逻辑见注释。
@GetMapping(value = "/executeTaskData")
public Result<ExecuteTaskDataVo> executeTaskData(@RequestParam String taskId) {
// 验证权限
Task task = permissionService.validateReadPermissionOnTask2(taskId,
SecurityUtils.getUserId(), true, true);
//查询bpmn信息
Process process = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess();
UserTask userTask = (UserTask)process.getFlowElement(task.getTaskDefinitionKey(), true);
if (userTask == null) {
throw new FlowableObjectNotFoundException("Can not find userTask by id " + task.getTaskDefinitionKey());
}
//拼装审批人表单和当前审批需要的表单
String startFormKey = formService.getStartFormKey(task.getProcessDefinitionId());
String taskFormKey = formService.getTaskFormKey(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
Object renderedStartForm = formService.getRenderedStartForm(task.getProcessDefinitionId());
Object renderedTaskForm = formService.getRenderedTaskForm(taskId);
Map<String, Object> variables = runtimeService.getVariables(task.getProcessInstanceId());
//获取流程实例信息
ProcessInstance processInstance =
runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
Boolean showBusinessKey = isShowBusinessKey(task.getProcessDefinitionId());
//组装输出参数
ExecuteTaskDataVo executeTaskDataVo = new ExecuteTaskDataVo();
executeTaskDataVo.setStartUserId(processInstance.getStartUserId());
executeTaskDataVo.setStartFormKey(startFormKey);
executeTaskDataVo.setTaskFormKey(taskFormKey);
executeTaskDataVo.setRenderedStartForm(renderedStartForm);
executeTaskDataVo.setRenderedTaskForm(renderedTaskForm);
executeTaskDataVo.setVariables(variables);
executeTaskDataVo.setShowBusinessKey(showBusinessKey);
// 当前任务是发起者
if (FlowableConstant.INITIATOR.equals(task.getTaskDefinitionKey())) {
executeTaskDataVo.setInitiator(true);
}
String buttons = FlowableUtils.getFlowableAttributeValue(userTask, FlowableConstant.BUTTONS);
if (buttons != null) {
executeTaskDataVo.setButtons(buttons.split(","));
}
historyService.createHistoricVariableInstanceQuery().processInstanceId("ss").variableNameLike("ss");
return Result.ok(executeTaskDataVo);
}
13.退回任务
在审批过程中,可以将任务退回到之前的某一个节点。
1.可退回任务列表
在退回时,可以指定具体的节点,那么需要查询之前节点列表,并组装成实体返回。
@GetMapping(value = "/backNodes")
public Result backNodes(@RequestParam String taskId) {
Resultresult = new Result<>();
// 调用service方法
List<FlowNodeResponse> datas = flowableTaskService.getBackNodes(taskId);
return Result.ok(datas);
}
public void stopProcessInstance(TaskRequest taskRequest) {
String taskId = taskRequest.getTaskId();
String userId = SecurityUtils.getUserId();
// 验证是否有权限结束流程
ProcessInstance processInstance = permissionService.validateStopProcessInstancePermissionOnTask(taskId, userId);
// 获取bpmn的对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
if (bpmnModel != null) {
Process process = bpmnModel.getMainProcess();
List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
// 查询结束节点的个数
if (endNodes != null && endNodes.size() > 0) {
// 添加过程意见
this.addComment(taskId, processInstance.getProcessInstanceId(), userId, CommentTypeEnum.ZZ,
taskRequest.getMessage());
// 获取第一个结束节点id
String endId = endNodes.get(0).getId();
// 获取流程定义信息
List<Execution> executions =
runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
List<String> executionIds = new ArrayList<>();
executions.forEach(execution -> executionIds.add(execution.getId()));
// 调用api更改状态为未激活
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId)
.changeState();
}
}
}
2.执行回退
使用提供的api更改任务状态,在之前除了很多验证判断,详细逻辑见注释。
@PutMapping(value = "/back")
public Result back(@RequestBody TaskRequest taskRequest) {
// 调用service方法
flowableTaskService.backTask(taskRequest);
return Result.ok();
}
public void backTask(TaskRequest taskRequest) {
String taskId = taskRequest.getTaskId();
String userId = SecurityUtils.getUserId();
Task task = permissionService.validateExcutePermissionOnTask(taskId, userId);
// 验证是否有权限回退
permissionService.validateTaskHasButtonPermission(task, ButtonsEnum.BACK);
String backSysMessage = "退回到" + taskRequest.getActivityName() + "。";
// 添加流程意见
this.addComment(taskId, task.getProcessInstanceId(), userId, CommentTypeEnum.TH,
backSysMessage + taskRequest.getMessage());
// 执行BackUserTaskCmd方法
String targetRealActivityId = managementService
.executeCommand(new BackUserTaskCmd(runtimeService, taskRequest.getTaskId(), taskRequest.getActivityId()));
// 退回发起者处理,退回到发起者,默认设置任务执行人为发起者
if (FlowableConstant.INITIATOR.equals(targetRealActivityId)) {
//获取开始人的username
String initiator = runtimeService.createProcessInstanceQuery()
.processInstanceId(task.getProcessInstanceId()).singleResult().getStartUserId();
//获取开始节点信息
List<Task> newTasks = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
for (Task newTask : newTasks) {
// 约定:发起者节点为 __initiator__
if (FlowableConstant.INITIATOR.equals(newTask.getTaskDefinitionKey())) {
if (CommonFlowableUtil.isEmpty(newTask.getAssignee())) {
//设置审批人信息
taskService.setAssignee(newTask.getId(), initiator);
}
}
}
}
}
public class BackUserTaskCmd implements Command<String>, Serializable {
public String execute(CommandContext commandContext) {
if (targetActivityId == null || targetActivityId.length() == 0) {
throw new FlowableException("TargetActivityId cannot be empty");
}
/// v6.5.1.28
TaskEntity task = CommandContextUtil.getProcessEngineConfiguration().getTaskServiceConfiguration()
.getTaskService().getTask(taskId);
if (task == null) {
throw new FlowableObjectNotFoundException("task " + taskId + " doesn't exist", Task.class);
}
// 获取task具体信息
String sourceActivityId = task.getTaskDefinitionKey();
String processInstanceId = task.getProcessInstanceId();
String processDefinitionId = task.getProcessDefinitionId();
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
FlowNode sourceFlowElement = (FlowNode)process.getFlowElement(sourceActivityId, true);
// 只支持从用户任务退回
if (!(sourceFlowElement instanceof UserTask)) {
throw new FlowableException("Task with id:" + taskId + " is not a UserTask");
}
FlowNode targetFlowElement = (FlowNode)process.getFlowElement(targetActivityId, true);
// 退回节点到当前节点不可达到,不允许退回
if (!FlowableUtils.isReachable(process, targetFlowElement, sourceFlowElement)) {
throw new FlowableException("Cannot back to [" + targetActivityId + "]");
}
// ps:目标节点如果相对当前节点是在子流程内部,则无法直接退回,目前处理是只能退回到子流程开始节点
String[] sourceAndTargetRealActivityId =
FlowableUtils.getSourceAndTargetRealActivityId(sourceFlowElement, targetFlowElement);
// 实际应操作的当前节点ID
String sourceRealActivityId = sourceAndTargetRealActivityId[0];
// 实际应操作的目标节点ID
String targetRealActivityId = sourceAndTargetRealActivityId[1];
Map<String, Set<String>> specialGatewayNodes = FlowableUtils.getSpecialGatewayElements(process);
// 当前节点处在的并行网关list
List<String> sourceInSpecialGatewayList = new ArrayList<>();
// 目标节点处在的并行网关list
List<String> targetInSpecialGatewayList = new ArrayList<>();
setSpecialGatewayList(sourceRealActivityId, targetRealActivityId, specialGatewayNodes,
sourceInSpecialGatewayList, targetInSpecialGatewayList);
// 实际应筛选的节点ID
Set<String> sourceRealAcitivtyIds = null;
// 若退回目标节点相对当前节点在并行网关中,则要找到相对当前节点最近的这个并行网关,后续做特殊处理
String targetRealSpecialGateway = null;
// 1.目标节点和当前节点都不在并行网关中
if (targetInSpecialGatewayList.isEmpty() && sourceInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
}
// 2.目标节点不在并行网关中、当前节点在并行网关中
else if (targetInSpecialGatewayList.isEmpty() && !sourceInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = specialGatewayNodes.get(sourceInSpecialGatewayList.get(0));
}
// 3.目标节点在并行网关中、当前节点不在并行网关中
else if (!targetInSpecialGatewayList.isEmpty() && sourceInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
targetRealSpecialGateway = targetInSpecialGatewayList.get(0);
}
// 4.目标节点和当前节点都在并行网关中
else {
int diffSpecialGatewayLevel =
FlowableUtils.getDiffLevel(sourceInSpecialGatewayList, targetInSpecialGatewayList);
// 在并行网关同一层且在同一分支
if (diffSpecialGatewayLevel == -1) {
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
} else {
// 当前节点最内层并行网关不被目标节点最内层并行网关包含
// 或理解为当前节点相对目标节点在并行网关外
// 只筛选当前节点的execution
if (sourceInSpecialGatewayList.size() == diffSpecialGatewayLevel) {
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
}
// 当前节点相对目标节点在并行网关内,应筛选相对目标节点最近的并行网关的所有节点的execution
else {
sourceRealAcitivtyIds =
specialGatewayNodes.get(sourceInSpecialGatewayList.get(diffSpecialGatewayLevel));
}
// 目标节点最内层并行网关包含当前节点最内层并行网关
// 或理解为目标节点相对当前节点在并行网关外
// 不做处理
if (targetInSpecialGatewayList.size() == diffSpecialGatewayLevel) {
}
// 目标节点相对当前节点在并行网关内
else {
targetRealSpecialGateway = targetInSpecialGatewayList.get(diffSpecialGatewayLevel);
}
}
}
// 筛选需要处理的execution
List<ExecutionEntity> realExecutions = this.getRealExecutions(commandContext, processInstanceId,
task.getExecutionId(), sourceRealActivityId, sourceRealAcitivtyIds);
// 执行退回,直接跳转到实际的 targetRealActivityId
List<String> realExecutionIds =
realExecutions.stream().map(ExecutionEntity::getId).collect(Collectors.toList());
//执行API
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId)
.moveExecutionsToSingleActivityId(realExecutionIds, targetRealActivityId).changeState();
// 目标节点相对当前节点处于并行网关内,需要特殊处理,需要手动生成并行网关汇聚节点(_end)的execution数据
if (targetRealSpecialGateway != null) {
createTargetInSpecialGatewayEndExecutions(commandContext, realExecutions, process,
targetInSpecialGatewayList, targetRealSpecialGateway);
}
return targetRealActivityId;
}
}
11.任务授权/TaskIdentityLinkController
任务授权不是必须业务流程,省略。