Commit 65a09182e714f25f8696300c14a06263f042ae4b
1 parent
d9ca52a4
仿钉钉流程设计- code review 构建节点连线修改
Showing
1 changed file
with
107 additions
and
56 deletions
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| ... | ... | @@ -25,7 +25,7 @@ import java.util.Map; |
| 25 | 25 | import java.util.Objects; |
| 26 | 26 | |
| 27 | 27 | import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_TIMEOUT; |
| 28 | -import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_NODE; | |
| 28 | +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.*; | |
| 29 | 29 | import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum.AUTO_REMINDER; |
| 30 | 30 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; |
| 31 | 31 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*; |
| ... | ... | @@ -84,78 +84,128 @@ public class SimpleModelUtils { |
| 84 | 84 | EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent); |
| 85 | 85 | |
| 86 | 86 | // 构建并添加节点之间的连线 Sequence Flow |
| 87 | - buildAndAddBpmnSequenceFlow(process, simpleModelNode, endEvent.getId()); | |
| 87 | + traverseNodeToBuildSequenceFlow(process, simpleModelNode, endEvent.getId()); | |
| 88 | 88 | // 自动布局 |
| 89 | 89 | new BpmnAutoLayout(bpmnModel).execute(); |
| 90 | 90 | return bpmnModel; |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | - private static void buildAndAddBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node, String targetId) { | |
| 94 | - // 节点为 null 或者 为END_EVENT 退出 | |
| 95 | - // TODO @jason:isValidNode;然后把 END_NODE 是不是拿到 switch (nodeType) { 那 return 哈?这样出口更统一一点? | |
| 96 | - if (node == null || node.getId() == null || END_NODE.getType().equals(node.getType())) { | |
| 93 | + private static void traverseNodeToBuildSequenceFlow(Process process, BpmSimpleModelNodeVO node, String targetNodeId) { | |
| 94 | + // 1.无效节点返回 | |
| 95 | + if (!isValidNode(node)) { | |
| 97 | 96 | return; |
| 98 | 97 | } |
| 99 | - BpmSimpleModelNodeVO childNode = node.getChildNode(); | |
| 98 | + | |
| 100 | 99 | // 如果是网关分支节点. 后续节点可能为 null。但不是 END_EVENT 节点 |
| 101 | - // TODO @芋艿:这个要不要挪到 START_NODE - INCLUSIVE_BRANCH_JOIN_NODE 待定;感觉 switch 那最终是分三个情况;branch、子节点、结束了;(每种情况的注释,需要写的更完整) | |
| 102 | - if (!BpmSimpleModelNodeType.isBranchNode(node.getType()) && (childNode == null || childNode.getId() == null)) { | |
| 103 | - SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetId, null, null, null); | |
| 104 | - mainProcess.addFlowElement(sequenceFlow); | |
| 105 | - return; | |
| 106 | - } | |
| 100 | + // TODO-DONE @芋艿:这个要不要挪到 START_NODE - INCLUSIVE_BRANCH_JOIN_NODE 待定;感觉 switch 那最终是分三个情况;branch、子节点、结束了;(每种情况的注释,需要写的更完整) | |
| 101 | +// if (!BpmSimpleModelNodeType.isBranchNode(node.getType()) && (childNode == null || childNode.getId() == null)) { | |
| 102 | +// SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetNodeId, null, null, null); | |
| 103 | +// process.addFlowElement(sequenceFlow); | |
| 104 | +// return; | |
| 105 | +// } | |
| 107 | 106 | BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType()); |
| 108 | 107 | Assert.notNull(nodeType, "模型节点类型不支持"); |
| 109 | - // TODO @jason:下面的 PARALLEL_BRANCH_FORK_NODE、CONDITION_BRANCH_NODE、INCLUSIVE_BRANCH_FORK_NODE 是不是就是 isBranchNode?如果是的话,貌似不用 swtich,而是 if else 分类处理呢。 | |
| 110 | - switch (nodeType) { | |
| 111 | - case START_NODE: | |
| 112 | - case APPROVE_NODE: | |
| 113 | - case COPY_NODE: | |
| 114 | - case PARALLEL_BRANCH_JOIN_NODE: | |
| 115 | - case INCLUSIVE_BRANCH_JOIN_NODE: { | |
| 108 | + BpmSimpleModelNodeVO childNode = node.getChildNode(); | |
| 109 | + // 2.1 普通节点 | |
| 110 | + if (!BpmSimpleModelNodeType.isBranchNode(node.getType())) { | |
| 111 | + // 2.1.1 结束节点退出递归 | |
| 112 | + if (nodeType == END_NODE) { | |
| 113 | + return; | |
| 114 | + } | |
| 115 | + if (!isValidNode(childNode)) { | |
| 116 | + // 2.1.2 普通节点且无孩子节点。分两种情况 | |
| 117 | + // a.结束节点 b. 条件分支的最后一个节点.与分支节点的孩子节点或聚合节点建立连线。 | |
| 118 | + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetNodeId, null, null, null); | |
| 119 | + process.addFlowElement(sequenceFlow); | |
| 120 | + } else { | |
| 121 | + // 2.1.3 普通节点且有孩子节点。建立连线 | |
| 116 | 122 | SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null, null); |
| 117 | - mainProcess.addFlowElement(sequenceFlow); | |
| 123 | + process.addFlowElement(sequenceFlow); | |
| 118 | 124 | // 递归调用后续节点 |
| 119 | - buildAndAddBpmnSequenceFlow(mainProcess, childNode, targetId); | |
| 120 | - break; | |
| 125 | + traverseNodeToBuildSequenceFlow(process, childNode, targetNodeId); | |
| 121 | 126 | } |
| 122 | - case PARALLEL_BRANCH_FORK_NODE: | |
| 123 | - case CONDITION_BRANCH_NODE: | |
| 124 | - case INCLUSIVE_BRANCH_FORK_NODE: { | |
| 125 | - // TODO @jason:这里 sequenceFlowTargetId 不建议做这样的 default。万一可能有 bug 哈;直接弄到对应的 136- 146 会更安全一点。 | |
| 126 | - String sequenceFlowTargetId = (childNode == null || childNode.getId() == null) ? targetId : childNode.getId(); | |
| 127 | - List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes(); | |
| 128 | - Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空"); | |
| 129 | - for (BpmSimpleModelNodeVO item : conditionNodes) { | |
| 130 | - // 构建表达式 | |
| 131 | - // TODO @jason:条件分支的情况下,需要分 item 搞的条件,和 conditionNodes 搞的条件 | |
| 132 | - String conditionExpression = buildConditionExpression(item); | |
| 133 | - | |
| 134 | - BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode(); | |
| 135 | - // TODO @jason:isValidNode | |
| 136 | - if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) { | |
| 137 | - // TODO @jason:会存在 item.name 未空的情况么?这个时候,要不要兜底处理拼接 | |
| 138 | - SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(), | |
| 139 | - item.getId(), item.getName(), conditionExpression); | |
| 140 | - mainProcess.addFlowElement(sequenceFlow); | |
| 141 | - // 递归调用后续节点 | |
| 142 | - // TODO @jason:最好也有个例子,嘿嘿;S4 | |
| 143 | - buildAndAddBpmnSequenceFlow(mainProcess, nextNodeOnCondition, sequenceFlowTargetId); | |
| 144 | - } else { | |
| 145 | - SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), sequenceFlowTargetId, | |
| 146 | - item.getId(), item.getName(), conditionExpression); | |
| 147 | - mainProcess.addFlowElement(sequenceFlow); | |
| 148 | - } | |
| 127 | + } else { | |
| 128 | + // 2.2 分支节点 | |
| 129 | + List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes(); | |
| 130 | + Assert.notEmpty(conditionNodes, "分支节点的条件节点不能为空"); | |
| 131 | + // 4.1 分支节点,遍历分支节点. 如下情况: | |
| 132 | + // 分支1、A->B->C->D->E 和 分支2、A->D->E。 A为分支节点, D为A孩子节点 | |
| 133 | + // 分支终点节点, 1. 分支节点有孩子节点时为孩子节点 2. 当分支节点孩子为无效节点时。分支嵌套时并且为分支最后一个节点 | |
| 134 | + String branchEndNodeId = isValidNode(childNode) ? childNode.getId() : targetNodeId ; | |
| 135 | + for (BpmSimpleModelNodeVO item : conditionNodes) { | |
| 136 | + // TODO @jason:条件分支的情况下,需要分 item 搞的条件,和 conditionNodes 搞的条件 | |
| 137 | + // 构建表达式 | |
| 138 | + String conditionExpression = buildConditionExpression(item); | |
| 139 | + BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode(); | |
| 140 | + // 4.2 分支有后续节点, 分支1: A->B->C->D | |
| 141 | + if (isValidNode(nextNodeOnCondition)) { | |
| 142 | + // 4.2.1 建立 A->B | |
| 143 | + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(), | |
| 144 | + item.getId(), item.getName(), conditionExpression); | |
| 145 | + process.addFlowElement(sequenceFlow); | |
| 146 | + // 4.2.2 递归调用后续节点连线。 建立 B->C->D 的连线 | |
| 147 | + traverseNodeToBuildSequenceFlow(process, nextNodeOnCondition, branchEndNodeId); | |
| 148 | + } else { | |
| 149 | + // 4.3 分支无后续节点 建立 A->D | |
| 150 | + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), branchEndNodeId, | |
| 151 | + item.getId(), item.getName(), conditionExpression); | |
| 152 | + process.addFlowElement(sequenceFlow); | |
| 149 | 153 | } |
| 150 | - // 递归调用后续节点 TODO @jason:最好有个例子哈 | |
| 151 | - buildAndAddBpmnSequenceFlow(mainProcess, childNode, targetId); | |
| 152 | - break; | |
| 153 | - } | |
| 154 | - default: { | |
| 155 | - // TODO 其它节点类型的实现 | |
| 156 | 154 | } |
| 155 | + // 递归调用后续节点 继续递归建立 D->E 的连线 | |
| 156 | + traverseNodeToBuildSequenceFlow(process, childNode, targetNodeId); | |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | + // TODO @jason:下面的 PARALLEL_BRANCH_FORK_NODE、CONDITION_BRANCH_NODE、INCLUSIVE_BRANCH_FORK_NODE 是不是就是 isBranchNode?如果是的话,貌似不用 swtich,而是 if else 分类处理呢。 | |
| 160 | +// switch (nodeType) { | |
| 161 | +// case START_NODE: | |
| 162 | +// case APPROVE_NODE: | |
| 163 | +// case COPY_NODE: | |
| 164 | +// case PARALLEL_BRANCH_JOIN_NODE: | |
| 165 | +// case INCLUSIVE_BRANCH_JOIN_NODE: { | |
| 166 | +// SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null, null); | |
| 167 | +// process.addFlowElement(sequenceFlow); | |
| 168 | +// // 递归调用后续节点 | |
| 169 | +// buildAndAddBpmnSequenceFlow(process, childNode, targetNodeId); | |
| 170 | +// break; | |
| 171 | +// } | |
| 172 | +// case PARALLEL_BRANCH_FORK_NODE: | |
| 173 | +// case CONDITION_BRANCH_NODE: | |
| 174 | +// case INCLUSIVE_BRANCH_FORK_NODE: { | |
| 175 | +// // TODO @jason:这里 sequenceFlowTargetId 不建议做这样的 default。万一可能有 bug 哈;直接弄到对应的 136- 146 会更安全一点。 | |
| 176 | +// String sequenceFlowTargetId = (childNode == null || childNode.getId() == null) ? targetNodeId : childNode.getId(); | |
| 177 | +// List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes(); | |
| 178 | +// Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空"); | |
| 179 | +// for (BpmSimpleModelNodeVO item : conditionNodes) { | |
| 180 | +// // 构建表达式 | |
| 181 | +// // TODO @jason:条件分支的情况下,需要分 item 搞的条件,和 conditionNodes 搞的条件 | |
| 182 | +// String conditionExpression = buildConditionExpression(item); | |
| 183 | +// | |
| 184 | +// BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode(); | |
| 185 | +// // TODO @jason:isValidNode | |
| 186 | +// if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) { | |
| 187 | +// // TODO @jason:会存在 item.name 未空的情况么?这个时候,要不要兜底处理拼接 | |
| 188 | +// SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(), | |
| 189 | +// item.getId(), item.getName(), conditionExpression); | |
| 190 | +// process.addFlowElement(sequenceFlow); | |
| 191 | +// // 递归调用后续节点 | |
| 192 | +// // TODO @jason:最好也有个例子,嘿嘿;S4 | |
| 193 | +// buildAndAddBpmnSequenceFlow(process, nextNodeOnCondition, sequenceFlowTargetId); | |
| 194 | +// } else { | |
| 195 | +// SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), sequenceFlowTargetId, | |
| 196 | +// item.getId(), item.getName(), conditionExpression); | |
| 197 | +// process.addFlowElement(sequenceFlow); | |
| 198 | +// } | |
| 199 | +// } | |
| 200 | +// // 递归调用后续节点 TODO @jason:最好有个例子哈 | |
| 201 | +// buildAndAddBpmnSequenceFlow(process, childNode, targetNodeId); | |
| 202 | +// break; | |
| 203 | +// } | |
| 204 | +// default: { | |
| 205 | +// // TODO 其它节点类型的实现 | |
| 206 | +// } | |
| 207 | +// } | |
| 208 | + | |
| 159 | 209 | } |
| 160 | 210 | |
| 161 | 211 | /** |
| ... | ... | @@ -283,6 +333,7 @@ public class SimpleModelUtils { |
| 283 | 333 | list.add(parallelGateway); |
| 284 | 334 | break; |
| 285 | 335 | } |
| 336 | + | |
| 286 | 337 | case INCLUSIVE_BRANCH_FORK_NODE: { |
| 287 | 338 | InclusiveGateway inclusiveGateway = convertInclusiveBranchNode(node, Boolean.TRUE); |
| 288 | 339 | list.add(inclusiveGateway); | ... | ... |