From 8f31e745dd838189ad4d5a9ff78d32b3ef0dcf85 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Tue, 28 May 2024 00:19:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1-=20code=20review=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/util/SimpleModelUtils.java | 133 +++++++++--------- .../definition/BpmModelServiceImpl.java | 2 +- 2 files changed, 70 insertions(+), 65 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 1ce5464f4..87d9097ba 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -19,6 +19,7 @@ import org.flowable.bpmn.BpmnAutoLayout; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -49,8 +50,9 @@ public class SimpleModelUtils { */ public static final String ANY_OF_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances > 0 }"; - // TODO @jason:建议方法名,改成 buildBpmnModel + // TODO-DONE @jason:建议方法名,改成 buildBpmnModel // TODO @yunai:注释需要完善下; + /** * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善) * @@ -59,11 +61,12 @@ public class SimpleModelUtils { * @param simpleModelNode 仿钉钉流程设计模型数据结构 * @return Bpmn Model */ - public static BpmnModel convertSimpleModelToBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) { + public static BpmnModel buildBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) { BpmnModel bpmnModel = new BpmnModel(); bpmnModel.setTargetNamespace(BPMN2_NAMESPACE); // TODO @jason:待定:是不是搞个自定义的 namespace; // TODO 芋艿:后续在 review - // 不加这个 解析 Message 会报 NPE 异常 + // @芋艿 这个 Message 可以去掉 暂时用不上 + // 不加这个 解析 Message 会报 NPE 异常 . Message rejectPostProcessMsg = new Message(); rejectPostProcessMsg.setName(REJECT_POST_PROCESS_MESSAGE_NAME); bpmnModel.addMessage(rejectPostProcessMsg); @@ -76,13 +79,9 @@ public class SimpleModelUtils { // 前端模型数据结构 // 从 SimpleModel 构建 FlowNode 并添加到 Main Process - buildAndAddBpmnFlowNode(simpleModelNode, process); + traverseNodeToBuildFlowNode(simpleModelNode, process); // 找到 end event EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent); - if (endEvent == null) { - // TODO 暂时为了兼容 单独构建 end event 节点. 后面去掉 - endEvent = buildAndAddBpmnEndEvent(process); - } // 构建并添加节点之间的连线 Sequence Flow buildAndAddBpmnSequenceFlow(process, simpleModelNode, endEvent.getId()); @@ -202,95 +201,100 @@ public class SimpleModelUtils { return sequenceFlow; } - // TODO @jason:要不改成 recursionNode 递归节点,然后把 build 名字让出来,专门用于构建各种 Node - // TODO @jason:simpleModelNode 改成 node,mainProcess 改成 process;更符合递归的感觉哈,处理当前节点 - private static void buildAndAddBpmnFlowNode(BpmSimpleModelNodeVO simpleModelNode, Process mainProcess) { - // 节点为 null 退出 - // TODO @jason:是不是写个 isValidNode 方法:判断是否为有效节点; - if (simpleModelNode == null || simpleModelNode.getId() == null) { + // TODO-DONE @jason:要不改成 recursionNode 递归节点,然后把 build 名字让出来,专门用于构建各种 Node + // @芋艿 改成了 traverseNodeToBuildFlowNode, 连线的叫 traverseNodeToBuildSequenceFlow + // TODO-DONE @jason:node 改成 node,process 改成 process;更符合递归的感觉哈,处理当前节点 + private static void traverseNodeToBuildFlowNode(BpmSimpleModelNodeVO node, Process process) { + // 判断是否有效节点 + // TODO-DONE @jason:是不是写个 isValidNode 方法:判断是否为有效节点; + if (!isValidNode(node)) { return; } - BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType()); + BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType()); Assert.notNull(nodeType, "模型节点类型不支持"); - // TODO @jason:要不抽个 buildNode 方法,然后返回一个 List,之后这个方法 addFlowElement;原因是,让当前这个方法,有主干逻辑;不然现在太长了; + + // TODO-DONE @jason:要不抽个 buildNode 方法,然后返回一个 List,之后这个方法 addFlowElement;原因是,让当前这个方法,有主干逻辑;不然现在太长了; + List flowElements = buildFlowNode(node, nodeType); + flowElements.forEach(process::addFlowElement); + + // 如果不是网关类型的接口, 并且chileNode为空退出 + // TODO-DONE @jason:建议这个判断去掉,可以更简洁一点;因为往下走;如果不成功,本身也就会结束哈;主要是,这里多了一个这样的判断,增加了理解成本; + // 如果是“分支”节点,则递归处理条件 + if (BpmSimpleModelNodeType.isBranchNode(node.getType()) + && ArrayUtil.isNotEmpty(node.getConditionNodes())) { + // TODO-DONE @jason:可以搞成 stream 写成一行哈 + node.getConditionNodes().forEach(item -> traverseNodeToBuildFlowNode(item.getChildNode(), process)); + } + + // 如果有“子”节点,则递归处理子节点 + // TODO-DONE @jason:这个,是不是不写判断,直接继续调用;因为本身 buildAndAddBpmnFlowNode 就会最开始判断了哈,就不重复判断了; + traverseNodeToBuildFlowNode(node.getChildNode(), process); + } + + private static boolean isValidNode(BpmSimpleModelNodeVO node) { + return node != null && node.getId() != null; + } + + private static List buildFlowNode(BpmSimpleModelNodeVO node, BpmSimpleModelNodeType nodeType) { + List list = new ArrayList<>(); switch (nodeType) { case START_EVENT: { - // TODO @jason:每个 nodeType,buildXXX 方法要不更明确,并且去掉 Bpmn; - StartEvent startEvent = buildBpmnStartEvent(simpleModelNode); - mainProcess.addFlowElement(startEvent); + // TODO-DONE @jason:每个 nodeType,buildXXX 方法要不更明确,并且去掉 Bpmn; + StartEvent startEvent = buildStartEvent(node); + list.add(startEvent); break; } case USER_TASK: { // TODO @jason:这个,搞成一个 buildUserTask,然后把下面这 2 种节点,搞在一起实现类;这样 buildNode 里面可以更简洁; // TODO @jason:这里还有个想法,是不是可以所有的都叫 buildXXXNode,然后里面有一些是 bpmn 相关的构建,叫做 buildBpmnUserTask,用于区分; // 获取用户任务的配置 - SimpleModelUserTaskConfig userTaskConfig = BeanUtil.toBean(simpleModelNode.getAttributes(), SimpleModelUserTaskConfig.class); - UserTask userTask = buildBpmnUserTask(simpleModelNode, userTaskConfig); - mainProcess.addFlowElement(userTask); + SimpleModelUserTaskConfig userTaskConfig = BeanUtil.toBean(node.getAttributes(), SimpleModelUserTaskConfig.class); + UserTask userTask = buildBpmnUserTask(node, userTaskConfig); + list.add(userTask); if (userTaskConfig.getTimeoutHandler() != null && userTaskConfig.getTimeoutHandler().getEnable()) { // 添加用户任务的 Timer Boundary Event, 用于任务的超时处理 BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler()); - mainProcess.addFlowElement(boundaryEvent); + //process.addFlowElement(boundaryEvent); + list.add(boundaryEvent); } break; } case COPY_TASK: { - ServiceTask serviceTask = buildBpmnServiceTask(simpleModelNode); - mainProcess.addFlowElement(serviceTask); + ServiceTask serviceTask = buildServiceTask(node); + list.add(serviceTask); break; } case EXCLUSIVE_GATEWAY: { - ExclusiveGateway exclusiveGateway = buildBpmnExclusiveGateway(simpleModelNode); - mainProcess.addFlowElement(exclusiveGateway); + ExclusiveGateway exclusiveGateway = buildExclusiveGateway(node); + list.add(exclusiveGateway); break; } case PARALLEL_GATEWAY_FORK: case PARALLEL_GATEWAY_JOIN: { - ParallelGateway parallelGateway = buildBpmnParallelGateway(simpleModelNode); - mainProcess.addFlowElement(parallelGateway); + ParallelGateway parallelGateway = buildParallelGateway(node); + list.add(parallelGateway); break; } case INCLUSIVE_GATEWAY_FORK: { - InclusiveGateway inclusiveGateway = buildBpmnInclusiveGateway(simpleModelNode, Boolean.TRUE); - mainProcess.addFlowElement(inclusiveGateway); + InclusiveGateway inclusiveGateway = buildInclusiveGateway(node, Boolean.TRUE); + list.add(inclusiveGateway); break; } case INCLUSIVE_GATEWAY_JOIN: { - InclusiveGateway inclusiveGateway = buildBpmnInclusiveGateway(simpleModelNode, Boolean.FALSE); - mainProcess.addFlowElement(inclusiveGateway); + InclusiveGateway inclusiveGateway = buildInclusiveGateway(node, Boolean.FALSE); + list.add(inclusiveGateway); break; } case END_EVENT: { - EndEvent endEvent = buildBpmnEndEvent(simpleModelNode); - mainProcess.addFlowElement(endEvent); + EndEvent endEvent = buildEndEvent(node); + list.add(endEvent); break; } default: { // TODO 其它节点类型的实现 } } - - // 如果不是网关类型的接口, 并且chileNode为空退出 - // TODO @jason:建议这个判断去掉,可以更简洁一点;因为往下走;如果不成功,本身也就会结束哈;主要是,这里多了一个这样的判断,增加了理解成本; - if (!BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) && simpleModelNode.getChildNode() == null) { - return; - } - - // 如果是“条件”节点,则递归处理条件 - if (BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) - && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) { - // TODO @jason:可以搞成 stream 写成一行哈; - for (BpmSimpleModelNodeVO node : simpleModelNode.getConditionNodes()) { - buildAndAddBpmnFlowNode(node.getChildNode(), mainProcess); - } - } - - // 如果有“子”节点,则递归处理子节点 - // chileNode不为空,递归添加子节点 - // TODO @jason:这个,是不是不写判断,直接继续调用;因为本身 buildAndAddBpmnFlowNode 就会最开始判断了哈,就不重复判断了; - if (simpleModelNode.getChildNode() != null) { - buildAndAddBpmnFlowNode(simpleModelNode.getChildNode(), mainProcess); - } + return list; } private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) { @@ -315,7 +319,7 @@ public class SimpleModelUtils { return boundaryEvent; } - private static ParallelGateway buildBpmnParallelGateway(BpmSimpleModelNodeVO node) { + private static ParallelGateway buildParallelGateway(BpmSimpleModelNodeVO node) { ParallelGateway parallelGateway = new ParallelGateway(); parallelGateway.setId(node.getId()); // TODO @jason:setName @@ -324,7 +328,7 @@ public class SimpleModelUtils { return parallelGateway; } - private static ServiceTask buildBpmnServiceTask(BpmSimpleModelNodeVO node) { + private static ServiceTask buildServiceTask(BpmSimpleModelNodeVO node) { ServiceTask serviceTask = new ServiceTask(); serviceTask.setId(node.getId()); serviceTask.setName(node.getName()); @@ -340,7 +344,8 @@ public class SimpleModelUtils { // 添加表单字段权限属性元素 // TODO @芋艿:这块关注下哈; List> fieldsPermissions = MapUtil.get(node.getAttributes(), - FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {}); + FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() { + }); addFormFieldsPermission(fieldsPermissions, serviceTask); return serviceTask; } @@ -354,7 +359,7 @@ public class SimpleModelUtils { addExtensionElement(flowElement, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM, candidateParam); } - private static ExclusiveGateway buildBpmnExclusiveGateway(BpmSimpleModelNodeVO node) { + private static ExclusiveGateway buildExclusiveGateway(BpmSimpleModelNodeVO node) { Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空"); ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); exclusiveGateway.setId(node.getId()); @@ -367,7 +372,7 @@ public class SimpleModelUtils { return exclusiveGateway; } - private static InclusiveGateway buildBpmnInclusiveGateway(BpmSimpleModelNodeVO node, Boolean isFork) { + private static InclusiveGateway buildInclusiveGateway(BpmSimpleModelNodeVO node, Boolean isFork) { InclusiveGateway inclusiveGateway = new InclusiveGateway(); inclusiveGateway.setId(node.getId()); // TODO @jason:这里是不是 setName 哈; @@ -483,7 +488,7 @@ public class SimpleModelUtils { // ========== 各种 build 节点的方法 ========== - private static StartEvent buildBpmnStartEvent(BpmSimpleModelNodeVO node) { + private static StartEvent buildStartEvent(BpmSimpleModelNodeVO node) { StartEvent startEvent = new StartEvent(); startEvent.setId(node.getId()); startEvent.setName(node.getName()); @@ -492,7 +497,7 @@ public class SimpleModelUtils { return startEvent; } - private static EndEvent buildBpmnEndEvent(BpmSimpleModelNodeVO node) { + private static EndEvent buildEndEvent(BpmSimpleModelNodeVO node) { EndEvent endEvent = new EndEvent(); endEvent.setId(node.getId()); endEvent.setName(node.getName()); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index 349b4200d..4762fac4d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -231,7 +231,7 @@ public class BpmModelServiceImpl implements BpmModelService { throw exception(MODEL_NOT_EXISTS); } // 1.2 JSON 转换成 bpmnModel - BpmnModel bpmnModel = SimpleModelUtils.convertSimpleModelToBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody()); + BpmnModel bpmnModel = SimpleModelUtils.buildBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody()); // 2.1 保存 Bpmn XML saveModelBpmnXml(model.getId(), StrUtil.utf8Bytes(BpmnModelUtils.getBpmnXml(bpmnModel))); // 2.2 保存 JSON 数据