仿钉钉流程设计- code review 构建节点连线修改

This commit is contained in:
jason 2024-05-29 09:48:28 +08:00
parent d9ca52a478
commit 65a09182e7

View File

@ -25,7 +25,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_TIMEOUT; import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_TIMEOUT;
import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_NODE; import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.*;
import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum.AUTO_REMINDER; import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum.AUTO_REMINDER;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*;
@ -84,78 +84,128 @@ public class SimpleModelUtils {
EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent); EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent);
// 构建并添加节点之间的连线 Sequence Flow // 构建并添加节点之间的连线 Sequence Flow
buildAndAddBpmnSequenceFlow(process, simpleModelNode, endEvent.getId()); traverseNodeToBuildSequenceFlow(process, simpleModelNode, endEvent.getId());
// 自动布局 // 自动布局
new BpmnAutoLayout(bpmnModel).execute(); new BpmnAutoLayout(bpmnModel).execute();
return bpmnModel; return bpmnModel;
} }
private static void buildAndAddBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node, String targetId) { private static void traverseNodeToBuildSequenceFlow(Process process, BpmSimpleModelNodeVO node, String targetNodeId) {
// 节点为 null 或者 为END_EVENT 退出 // 1.无效节点返回
// TODO @jasonisValidNode然后把 END_NODE 是不是拿到 switch (nodeType) { return 这样出口更统一一点 if (!isValidNode(node)) {
if (node == null || node.getId() == null || END_NODE.getType().equals(node.getType())) {
return; return;
} }
BpmSimpleModelNodeVO childNode = node.getChildNode();
// 如果是网关分支节点. 后续节点可能为 null但不是 END_EVENT 节点 // 如果是网关分支节点. 后续节点可能为 null但不是 END_EVENT 节点
// TODO @芋艿这个要不要挪到 START_NODE - INCLUSIVE_BRANCH_JOIN_NODE 待定感觉 switch 那最终是分三个情况branch子节点结束了每种情况的注释需要写的更完整 // TODO-DONE @芋艿这个要不要挪到 START_NODE - INCLUSIVE_BRANCH_JOIN_NODE 待定感觉 switch 那最终是分三个情况branch子节点结束了每种情况的注释需要写的更完整
if (!BpmSimpleModelNodeType.isBranchNode(node.getType()) && (childNode == null || childNode.getId() == null)) { // if (!BpmSimpleModelNodeType.isBranchNode(node.getType()) && (childNode == null || childNode.getId() == null)) {
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetId, null, null, null); // SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetNodeId, null, null, null);
mainProcess.addFlowElement(sequenceFlow); // process.addFlowElement(sequenceFlow);
return; // return;
} // }
BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType()); BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
Assert.notNull(nodeType, "模型节点类型不支持"); Assert.notNull(nodeType, "模型节点类型不支持");
// TODO @jason下面的 PARALLEL_BRANCH_FORK_NODECONDITION_BRANCH_NODEINCLUSIVE_BRANCH_FORK_NODE 是不是就是 isBranchNode如果是的话貌似不用 swtich而是 if else 分类处理呢 BpmSimpleModelNodeVO childNode = node.getChildNode();
switch (nodeType) { // 2.1 普通节点
case START_NODE: if (!BpmSimpleModelNodeType.isBranchNode(node.getType())) {
case APPROVE_NODE: // 2.1.1 结束节点退出递归
case COPY_NODE: if (nodeType == END_NODE) {
case PARALLEL_BRANCH_JOIN_NODE: return;
case INCLUSIVE_BRANCH_JOIN_NODE: {
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null, null);
mainProcess.addFlowElement(sequenceFlow);
// 递归调用后续节点
buildAndAddBpmnSequenceFlow(mainProcess, childNode, targetId);
break;
} }
case PARALLEL_BRANCH_FORK_NODE: if (!isValidNode(childNode)) {
case CONDITION_BRANCH_NODE: // 2.1.2 普通节点且无孩子节点分两种情况
case INCLUSIVE_BRANCH_FORK_NODE: { // a.结束节点 b. 条件分支的最后一个节点.与分支节点的孩子节点或聚合节点建立连线
// TODO @jason这里 sequenceFlowTargetId 不建议做这样的 default万一可能有 bug 直接弄到对应的 136- 146 会更安全一点 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetNodeId, null, null, null);
String sequenceFlowTargetId = (childNode == null || childNode.getId() == null) ? targetId : childNode.getId(); process.addFlowElement(sequenceFlow);
} else {
// 2.1.3 普通节点且有孩子节点建立连线
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null, null);
process.addFlowElement(sequenceFlow);
// 递归调用后续节点
traverseNodeToBuildSequenceFlow(process, childNode, targetNodeId);
}
} else {
// 2.2 分支节点
List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes(); List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes();
Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空"); Assert.notEmpty(conditionNodes, "分支节点的条件节点不能为空");
// 4.1 分支节点遍历分支节点. 如下情况:
// 分支1A->B->C->D->E 分支2A->D->E A为分支节点, D为A孩子节点
// 分支终点节点 1. 分支节点有孩子节点时为孩子节点 2. 当分支节点孩子为无效节点时分支嵌套时并且为分支最后一个节点
String branchEndNodeId = isValidNode(childNode) ? childNode.getId() : targetNodeId ;
for (BpmSimpleModelNodeVO item : conditionNodes) { for (BpmSimpleModelNodeVO item : conditionNodes) {
// 构建表达式
// TODO @jason条件分支的情况下需要分 item 搞的条件 conditionNodes 搞的条件 // TODO @jason条件分支的情况下需要分 item 搞的条件 conditionNodes 搞的条件
// 构建表达式
String conditionExpression = buildConditionExpression(item); String conditionExpression = buildConditionExpression(item);
BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode(); BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode();
// TODO @jasonisValidNode // 4.2 分支有后续节点, 分支1: A->B->C->D
if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) { if (isValidNode(nextNodeOnCondition)) {
// TODO @jason会存在 item.name 未空的情况么这个时候要不要兜底处理拼接 // 4.2.1 建立 A->B
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(), SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(),
item.getId(), item.getName(), conditionExpression); item.getId(), item.getName(), conditionExpression);
mainProcess.addFlowElement(sequenceFlow); process.addFlowElement(sequenceFlow);
// 递归调用后续节点 // 4.2.2 递归调用后续节点连线 建立 B->C->D 的连线
// TODO @jason最好也有个例子嘿嘿S4 traverseNodeToBuildSequenceFlow(process, nextNodeOnCondition, branchEndNodeId);
buildAndAddBpmnSequenceFlow(mainProcess, nextNodeOnCondition, sequenceFlowTargetId);
} else { } else {
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), sequenceFlowTargetId, // 4.3 分支无后续节点 建立 A->D
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), branchEndNodeId,
item.getId(), item.getName(), conditionExpression); item.getId(), item.getName(), conditionExpression);
mainProcess.addFlowElement(sequenceFlow); process.addFlowElement(sequenceFlow);
} }
} }
// 递归调用后续节点 TODO @jason最好有个例子哈 // 递归调用后续节点 继续递归建立 D->E 的连线
buildAndAddBpmnSequenceFlow(mainProcess, childNode, targetId); traverseNodeToBuildSequenceFlow(process, childNode, targetNodeId);
break;
}
default: {
// TODO 其它节点类型的实现
}
} }
// TODO @jason下面的 PARALLEL_BRANCH_FORK_NODECONDITION_BRANCH_NODEINCLUSIVE_BRANCH_FORK_NODE 是不是就是 isBranchNode如果是的话貌似不用 swtich而是 if else 分类处理呢
// switch (nodeType) {
// case START_NODE:
// case APPROVE_NODE:
// case COPY_NODE:
// case PARALLEL_BRANCH_JOIN_NODE:
// case INCLUSIVE_BRANCH_JOIN_NODE: {
// SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null, null);
// process.addFlowElement(sequenceFlow);
// // 递归调用后续节点
// buildAndAddBpmnSequenceFlow(process, childNode, targetNodeId);
// break;
// }
// case PARALLEL_BRANCH_FORK_NODE:
// case CONDITION_BRANCH_NODE:
// case INCLUSIVE_BRANCH_FORK_NODE: {
// // TODO @jason这里 sequenceFlowTargetId 不建议做这样的 default万一可能有 bug 直接弄到对应的 136- 146 会更安全一点
// String sequenceFlowTargetId = (childNode == null || childNode.getId() == null) ? targetNodeId : childNode.getId();
// List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes();
// Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空");
// for (BpmSimpleModelNodeVO item : conditionNodes) {
// // 构建表达式
// // TODO @jason条件分支的情况下需要分 item 搞的条件 conditionNodes 搞的条件
// String conditionExpression = buildConditionExpression(item);
//
// BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode();
// // TODO @jasonisValidNode
// if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) {
// // TODO @jason会存在 item.name 未空的情况么这个时候要不要兜底处理拼接
// SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(),
// item.getId(), item.getName(), conditionExpression);
// process.addFlowElement(sequenceFlow);
// // 递归调用后续节点
// // TODO @jason最好也有个例子嘿嘿S4
// buildAndAddBpmnSequenceFlow(process, nextNodeOnCondition, sequenceFlowTargetId);
// } else {
// SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), sequenceFlowTargetId,
// item.getId(), item.getName(), conditionExpression);
// process.addFlowElement(sequenceFlow);
// }
// }
// // 递归调用后续节点 TODO @jason最好有个例子哈
// buildAndAddBpmnSequenceFlow(process, childNode, targetNodeId);
// break;
// }
// default: {
// // TODO 其它节点类型的实现
// }
// }
} }
/** /**
@ -283,6 +333,7 @@ public class SimpleModelUtils {
list.add(parallelGateway); list.add(parallelGateway);
break; break;
} }
case INCLUSIVE_BRANCH_FORK_NODE: { case INCLUSIVE_BRANCH_FORK_NODE: {
InclusiveGateway inclusiveGateway = convertInclusiveBranchNode(node, Boolean.TRUE); InclusiveGateway inclusiveGateway = convertInclusiveBranchNode(node, Boolean.TRUE);
list.add(inclusiveGateway); list.add(inclusiveGateway);