Commit 8f31e745dd838189ad4d5a9ff78d32b3ef0dcf85

Authored by jason
1 parent 4d176c84

仿钉钉流程设计- code review 修改

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; @@ -19,6 +19,7 @@ import org.flowable.bpmn.BpmnAutoLayout;
19 import org.flowable.bpmn.model.Process; 19 import org.flowable.bpmn.model.Process;
20 import org.flowable.bpmn.model.*; 20 import org.flowable.bpmn.model.*;
21 21
  22 +import java.util.ArrayList;
22 import java.util.List; 23 import java.util.List;
23 import java.util.Map; 24 import java.util.Map;
24 import java.util.Objects; 25 import java.util.Objects;
@@ -49,8 +50,9 @@ public class SimpleModelUtils { @@ -49,8 +50,9 @@ public class SimpleModelUtils {
49 */ 50 */
50 public static final String ANY_OF_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances > 0 }"; 51 public static final String ANY_OF_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances > 0 }";
51 52
52 - // TODO @jason:建议方法名,改成 buildBpmnModel 53 + // TODO-DONE @jason:建议方法名,改成 buildBpmnModel
53 // TODO @yunai:注释需要完善下; 54 // TODO @yunai:注释需要完善下;
  55 +
54 /** 56 /**
55 * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善) 57 * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善)
56 * 58 *
@@ -59,11 +61,12 @@ public class SimpleModelUtils { @@ -59,11 +61,12 @@ public class SimpleModelUtils {
59 * @param simpleModelNode 仿钉钉流程设计模型数据结构 61 * @param simpleModelNode 仿钉钉流程设计模型数据结构
60 * @return Bpmn Model 62 * @return Bpmn Model
61 */ 63 */
62 - public static BpmnModel convertSimpleModelToBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) { 64 + public static BpmnModel buildBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) {
63 BpmnModel bpmnModel = new BpmnModel(); 65 BpmnModel bpmnModel = new BpmnModel();
64 bpmnModel.setTargetNamespace(BPMN2_NAMESPACE); // TODO @jason:待定:是不是搞个自定义的 namespace; 66 bpmnModel.setTargetNamespace(BPMN2_NAMESPACE); // TODO @jason:待定:是不是搞个自定义的 namespace;
65 // TODO 芋艿:后续在 review 67 // TODO 芋艿:后续在 review
66 - // 不加这个 解析 Message 会报 NPE 异常 68 + // @芋艿 这个 Message 可以去掉 暂时用不上
  69 + // 不加这个 解析 Message 会报 NPE 异常 .
67 Message rejectPostProcessMsg = new Message(); 70 Message rejectPostProcessMsg = new Message();
68 rejectPostProcessMsg.setName(REJECT_POST_PROCESS_MESSAGE_NAME); 71 rejectPostProcessMsg.setName(REJECT_POST_PROCESS_MESSAGE_NAME);
69 bpmnModel.addMessage(rejectPostProcessMsg); 72 bpmnModel.addMessage(rejectPostProcessMsg);
@@ -76,13 +79,9 @@ public class SimpleModelUtils { @@ -76,13 +79,9 @@ public class SimpleModelUtils {
76 79
77 // 前端模型数据结构 80 // 前端模型数据结构
78 // 从 SimpleModel 构建 FlowNode 并添加到 Main Process 81 // 从 SimpleModel 构建 FlowNode 并添加到 Main Process
79 - buildAndAddBpmnFlowNode(simpleModelNode, process); 82 + traverseNodeToBuildFlowNode(simpleModelNode, process);
80 // 找到 end event 83 // 找到 end event
81 EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent); 84 EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent);
82 - if (endEvent == null) {  
83 - // TODO 暂时为了兼容 单独构建 end event 节点. 后面去掉  
84 - endEvent = buildAndAddBpmnEndEvent(process);  
85 - }  
86 85
87 // 构建并添加节点之间的连线 Sequence Flow 86 // 构建并添加节点之间的连线 Sequence Flow
88 buildAndAddBpmnSequenceFlow(process, simpleModelNode, endEvent.getId()); 87 buildAndAddBpmnSequenceFlow(process, simpleModelNode, endEvent.getId());
@@ -202,95 +201,100 @@ public class SimpleModelUtils { @@ -202,95 +201,100 @@ public class SimpleModelUtils {
202 return sequenceFlow; 201 return sequenceFlow;
203 } 202 }
204 203
205 - // TODO @jason:要不改成 recursionNode 递归节点,然后把 build 名字让出来,专门用于构建各种 Node  
206 - // TODO @jason:simpleModelNode 改成 node,mainProcess 改成 process;更符合递归的感觉哈,处理当前节点  
207 - private static void buildAndAddBpmnFlowNode(BpmSimpleModelNodeVO simpleModelNode, Process mainProcess) {  
208 - // 节点为 null 退出  
209 - // TODO @jason:是不是写个 isValidNode 方法:判断是否为有效节点;  
210 - if (simpleModelNode == null || simpleModelNode.getId() == null) { 204 + // TODO-DONE @jason:要不改成 recursionNode 递归节点,然后把 build 名字让出来,专门用于构建各种 Node
  205 + // @芋艿 改成了 traverseNodeToBuildFlowNode, 连线的叫 traverseNodeToBuildSequenceFlow
  206 + // TODO-DONE @jason:node 改成 node,process 改成 process;更符合递归的感觉哈,处理当前节点
  207 + private static void traverseNodeToBuildFlowNode(BpmSimpleModelNodeVO node, Process process) {
  208 + // 判断是否有效节点
  209 + // TODO-DONE @jason:是不是写个 isValidNode 方法:判断是否为有效节点;
  210 + if (!isValidNode(node)) {
211 return; 211 return;
212 } 212 }
213 - BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType()); 213 + BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
214 Assert.notNull(nodeType, "模型节点类型不支持"); 214 Assert.notNull(nodeType, "模型节点类型不支持");
215 - // TODO @jason:要不抽个 buildNode 方法,然后返回一个 List<FlowElement>,之后这个方法 addFlowElement;原因是,让当前这个方法,有主干逻辑;不然现在太长了; 215 +
  216 + // TODO-DONE @jason:要不抽个 buildNode 方法,然后返回一个 List<FlowElement>,之后这个方法 addFlowElement;原因是,让当前这个方法,有主干逻辑;不然现在太长了;
  217 + List<FlowElement> flowElements = buildFlowNode(node, nodeType);
  218 + flowElements.forEach(process::addFlowElement);
  219 +
  220 + // 如果不是网关类型的接口, 并且chileNode为空退出
  221 + // TODO-DONE @jason:建议这个判断去掉,可以更简洁一点;因为往下走;如果不成功,本身也就会结束哈;主要是,这里多了一个这样的判断,增加了理解成本;
  222 + // 如果是“分支”节点,则递归处理条件
  223 + if (BpmSimpleModelNodeType.isBranchNode(node.getType())
  224 + && ArrayUtil.isNotEmpty(node.getConditionNodes())) {
  225 + // TODO-DONE @jason:可以搞成 stream 写成一行哈
  226 + node.getConditionNodes().forEach(item -> traverseNodeToBuildFlowNode(item.getChildNode(), process));
  227 + }
  228 +
  229 + // 如果有“子”节点,则递归处理子节点
  230 + // TODO-DONE @jason:这个,是不是不写判断,直接继续调用;因为本身 buildAndAddBpmnFlowNode 就会最开始判断了哈,就不重复判断了;
  231 + traverseNodeToBuildFlowNode(node.getChildNode(), process);
  232 + }
  233 +
  234 + private static boolean isValidNode(BpmSimpleModelNodeVO node) {
  235 + return node != null && node.getId() != null;
  236 + }
  237 +
  238 + private static List<FlowElement> buildFlowNode(BpmSimpleModelNodeVO node, BpmSimpleModelNodeType nodeType) {
  239 + List<FlowElement> list = new ArrayList<>();
216 switch (nodeType) { 240 switch (nodeType) {
217 case START_EVENT: { 241 case START_EVENT: {
218 - // TODO @jason:每个 nodeType,buildXXX 方法要不更明确,并且去掉 Bpmn;  
219 - StartEvent startEvent = buildBpmnStartEvent(simpleModelNode);  
220 - mainProcess.addFlowElement(startEvent); 242 + // TODO-DONE @jason:每个 nodeType,buildXXX 方法要不更明确,并且去掉 Bpmn;
  243 + StartEvent startEvent = buildStartEvent(node);
  244 + list.add(startEvent);
221 break; 245 break;
222 } 246 }
223 case USER_TASK: { 247 case USER_TASK: {
224 // TODO @jason:这个,搞成一个 buildUserTask,然后把下面这 2 种节点,搞在一起实现类;这样 buildNode 里面可以更简洁; 248 // TODO @jason:这个,搞成一个 buildUserTask,然后把下面这 2 种节点,搞在一起实现类;这样 buildNode 里面可以更简洁;
225 // TODO @jason:这里还有个想法,是不是可以所有的都叫 buildXXXNode,然后里面有一些是 bpmn 相关的构建,叫做 buildBpmnUserTask,用于区分; 249 // TODO @jason:这里还有个想法,是不是可以所有的都叫 buildXXXNode,然后里面有一些是 bpmn 相关的构建,叫做 buildBpmnUserTask,用于区分;
226 // 获取用户任务的配置 250 // 获取用户任务的配置
227 - SimpleModelUserTaskConfig userTaskConfig = BeanUtil.toBean(simpleModelNode.getAttributes(), SimpleModelUserTaskConfig.class);  
228 - UserTask userTask = buildBpmnUserTask(simpleModelNode, userTaskConfig);  
229 - mainProcess.addFlowElement(userTask); 251 + SimpleModelUserTaskConfig userTaskConfig = BeanUtil.toBean(node.getAttributes(), SimpleModelUserTaskConfig.class);
  252 + UserTask userTask = buildBpmnUserTask(node, userTaskConfig);
  253 + list.add(userTask);
230 if (userTaskConfig.getTimeoutHandler() != null && userTaskConfig.getTimeoutHandler().getEnable()) { 254 if (userTaskConfig.getTimeoutHandler() != null && userTaskConfig.getTimeoutHandler().getEnable()) {
231 // 添加用户任务的 Timer Boundary Event, 用于任务的超时处理 255 // 添加用户任务的 Timer Boundary Event, 用于任务的超时处理
232 BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler()); 256 BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler());
233 - mainProcess.addFlowElement(boundaryEvent); 257 + //process.addFlowElement(boundaryEvent);
  258 + list.add(boundaryEvent);
234 } 259 }
235 break; 260 break;
236 } 261 }
237 case COPY_TASK: { 262 case COPY_TASK: {
238 - ServiceTask serviceTask = buildBpmnServiceTask(simpleModelNode);  
239 - mainProcess.addFlowElement(serviceTask); 263 + ServiceTask serviceTask = buildServiceTask(node);
  264 + list.add(serviceTask);
240 break; 265 break;
241 } 266 }
242 case EXCLUSIVE_GATEWAY: { 267 case EXCLUSIVE_GATEWAY: {
243 - ExclusiveGateway exclusiveGateway = buildBpmnExclusiveGateway(simpleModelNode);  
244 - mainProcess.addFlowElement(exclusiveGateway); 268 + ExclusiveGateway exclusiveGateway = buildExclusiveGateway(node);
  269 + list.add(exclusiveGateway);
245 break; 270 break;
246 } 271 }
247 case PARALLEL_GATEWAY_FORK: 272 case PARALLEL_GATEWAY_FORK:
248 case PARALLEL_GATEWAY_JOIN: { 273 case PARALLEL_GATEWAY_JOIN: {
249 - ParallelGateway parallelGateway = buildBpmnParallelGateway(simpleModelNode);  
250 - mainProcess.addFlowElement(parallelGateway); 274 + ParallelGateway parallelGateway = buildParallelGateway(node);
  275 + list.add(parallelGateway);
251 break; 276 break;
252 } 277 }
253 case INCLUSIVE_GATEWAY_FORK: { 278 case INCLUSIVE_GATEWAY_FORK: {
254 - InclusiveGateway inclusiveGateway = buildBpmnInclusiveGateway(simpleModelNode, Boolean.TRUE);  
255 - mainProcess.addFlowElement(inclusiveGateway); 279 + InclusiveGateway inclusiveGateway = buildInclusiveGateway(node, Boolean.TRUE);
  280 + list.add(inclusiveGateway);
256 break; 281 break;
257 } 282 }
258 case INCLUSIVE_GATEWAY_JOIN: { 283 case INCLUSIVE_GATEWAY_JOIN: {
259 - InclusiveGateway inclusiveGateway = buildBpmnInclusiveGateway(simpleModelNode, Boolean.FALSE);  
260 - mainProcess.addFlowElement(inclusiveGateway); 284 + InclusiveGateway inclusiveGateway = buildInclusiveGateway(node, Boolean.FALSE);
  285 + list.add(inclusiveGateway);
261 break; 286 break;
262 } 287 }
263 case END_EVENT: { 288 case END_EVENT: {
264 - EndEvent endEvent = buildBpmnEndEvent(simpleModelNode);  
265 - mainProcess.addFlowElement(endEvent); 289 + EndEvent endEvent = buildEndEvent(node);
  290 + list.add(endEvent);
266 break; 291 break;
267 } 292 }
268 default: { 293 default: {
269 // TODO 其它节点类型的实现 294 // TODO 其它节点类型的实现
270 } 295 }
271 } 296 }
272 -  
273 - // 如果不是网关类型的接口, 并且chileNode为空退出  
274 - // TODO @jason:建议这个判断去掉,可以更简洁一点;因为往下走;如果不成功,本身也就会结束哈;主要是,这里多了一个这样的判断,增加了理解成本;  
275 - if (!BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) && simpleModelNode.getChildNode() == null) {  
276 - return;  
277 - }  
278 -  
279 - // 如果是“条件”节点,则递归处理条件  
280 - if (BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType())  
281 - && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {  
282 - // TODO @jason:可以搞成 stream 写成一行哈;  
283 - for (BpmSimpleModelNodeVO node : simpleModelNode.getConditionNodes()) {  
284 - buildAndAddBpmnFlowNode(node.getChildNode(), mainProcess);  
285 - }  
286 - }  
287 -  
288 - // 如果有“子”节点,则递归处理子节点  
289 - // chileNode不为空,递归添加子节点  
290 - // TODO @jason:这个,是不是不写判断,直接继续调用;因为本身 buildAndAddBpmnFlowNode 就会最开始判断了哈,就不重复判断了;  
291 - if (simpleModelNode.getChildNode() != null) {  
292 - buildAndAddBpmnFlowNode(simpleModelNode.getChildNode(), mainProcess);  
293 - } 297 + return list;
294 } 298 }
295 299
296 private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) { 300 private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) {
@@ -315,7 +319,7 @@ public class SimpleModelUtils { @@ -315,7 +319,7 @@ public class SimpleModelUtils {
315 return boundaryEvent; 319 return boundaryEvent;
316 } 320 }
317 321
318 - private static ParallelGateway buildBpmnParallelGateway(BpmSimpleModelNodeVO node) { 322 + private static ParallelGateway buildParallelGateway(BpmSimpleModelNodeVO node) {
319 ParallelGateway parallelGateway = new ParallelGateway(); 323 ParallelGateway parallelGateway = new ParallelGateway();
320 parallelGateway.setId(node.getId()); 324 parallelGateway.setId(node.getId());
321 // TODO @jason:setName 325 // TODO @jason:setName
@@ -324,7 +328,7 @@ public class SimpleModelUtils { @@ -324,7 +328,7 @@ public class SimpleModelUtils {
324 return parallelGateway; 328 return parallelGateway;
325 } 329 }
326 330
327 - private static ServiceTask buildBpmnServiceTask(BpmSimpleModelNodeVO node) { 331 + private static ServiceTask buildServiceTask(BpmSimpleModelNodeVO node) {
328 ServiceTask serviceTask = new ServiceTask(); 332 ServiceTask serviceTask = new ServiceTask();
329 serviceTask.setId(node.getId()); 333 serviceTask.setId(node.getId());
330 serviceTask.setName(node.getName()); 334 serviceTask.setName(node.getName());
@@ -340,7 +344,8 @@ public class SimpleModelUtils { @@ -340,7 +344,8 @@ public class SimpleModelUtils {
340 // 添加表单字段权限属性元素 344 // 添加表单字段权限属性元素
341 // TODO @芋艿:这块关注下哈; 345 // TODO @芋艿:这块关注下哈;
342 List<Map<String, String>> fieldsPermissions = MapUtil.get(node.getAttributes(), 346 List<Map<String, String>> fieldsPermissions = MapUtil.get(node.getAttributes(),
343 - FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {}); 347 + FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {
  348 + });
344 addFormFieldsPermission(fieldsPermissions, serviceTask); 349 addFormFieldsPermission(fieldsPermissions, serviceTask);
345 return serviceTask; 350 return serviceTask;
346 } 351 }
@@ -354,7 +359,7 @@ public class SimpleModelUtils { @@ -354,7 +359,7 @@ public class SimpleModelUtils {
354 addExtensionElement(flowElement, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM, candidateParam); 359 addExtensionElement(flowElement, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM, candidateParam);
355 } 360 }
356 361
357 - private static ExclusiveGateway buildBpmnExclusiveGateway(BpmSimpleModelNodeVO node) { 362 + private static ExclusiveGateway buildExclusiveGateway(BpmSimpleModelNodeVO node) {
358 Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空"); 363 Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
359 ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); 364 ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
360 exclusiveGateway.setId(node.getId()); 365 exclusiveGateway.setId(node.getId());
@@ -367,7 +372,7 @@ public class SimpleModelUtils { @@ -367,7 +372,7 @@ public class SimpleModelUtils {
367 return exclusiveGateway; 372 return exclusiveGateway;
368 } 373 }
369 374
370 - private static InclusiveGateway buildBpmnInclusiveGateway(BpmSimpleModelNodeVO node, Boolean isFork) { 375 + private static InclusiveGateway buildInclusiveGateway(BpmSimpleModelNodeVO node, Boolean isFork) {
371 InclusiveGateway inclusiveGateway = new InclusiveGateway(); 376 InclusiveGateway inclusiveGateway = new InclusiveGateway();
372 inclusiveGateway.setId(node.getId()); 377 inclusiveGateway.setId(node.getId());
373 // TODO @jason:这里是不是 setName 哈; 378 // TODO @jason:这里是不是 setName 哈;
@@ -483,7 +488,7 @@ public class SimpleModelUtils { @@ -483,7 +488,7 @@ public class SimpleModelUtils {
483 488
484 // ========== 各种 build 节点的方法 ========== 489 // ========== 各种 build 节点的方法 ==========
485 490
486 - private static StartEvent buildBpmnStartEvent(BpmSimpleModelNodeVO node) { 491 + private static StartEvent buildStartEvent(BpmSimpleModelNodeVO node) {
487 StartEvent startEvent = new StartEvent(); 492 StartEvent startEvent = new StartEvent();
488 startEvent.setId(node.getId()); 493 startEvent.setId(node.getId());
489 startEvent.setName(node.getName()); 494 startEvent.setName(node.getName());
@@ -492,7 +497,7 @@ public class SimpleModelUtils { @@ -492,7 +497,7 @@ public class SimpleModelUtils {
492 return startEvent; 497 return startEvent;
493 } 498 }
494 499
495 - private static EndEvent buildBpmnEndEvent(BpmSimpleModelNodeVO node) { 500 + private static EndEvent buildEndEvent(BpmSimpleModelNodeVO node) {
496 EndEvent endEvent = new EndEvent(); 501 EndEvent endEvent = new EndEvent();
497 endEvent.setId(node.getId()); 502 endEvent.setId(node.getId());
498 endEvent.setName(node.getName()); 503 endEvent.setName(node.getName());
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 { @@ -231,7 +231,7 @@ public class BpmModelServiceImpl implements BpmModelService {
231 throw exception(MODEL_NOT_EXISTS); 231 throw exception(MODEL_NOT_EXISTS);
232 } 232 }
233 // 1.2 JSON 转换成 bpmnModel 233 // 1.2 JSON 转换成 bpmnModel
234 - BpmnModel bpmnModel = SimpleModelUtils.convertSimpleModelToBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody()); 234 + BpmnModel bpmnModel = SimpleModelUtils.buildBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody());
235 // 2.1 保存 Bpmn XML 235 // 2.1 保存 Bpmn XML
236 saveModelBpmnXml(model.getId(), StrUtil.utf8Bytes(BpmnModelUtils.getBpmnXml(bpmnModel))); 236 saveModelBpmnXml(model.getId(), StrUtil.utf8Bytes(BpmnModelUtils.getBpmnXml(bpmnModel)));
237 // 2.2 保存 JSON 数据 237 // 2.2 保存 JSON 数据