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 19 import org.flowable.bpmn.model.Process;
20 20 import org.flowable.bpmn.model.*;
21 21  
  22 +import java.util.ArrayList;
22 23 import java.util.List;
23 24 import java.util.Map;
24 25 import java.util.Objects;
... ... @@ -49,8 +50,9 @@ public class SimpleModelUtils {
49 50 */
50 51 public static final String ANY_OF_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances > 0 }";
51 52  
52   - // TODO @jason:建议方法名,改成 buildBpmnModel
  53 + // TODO-DONE @jason:建议方法名,改成 buildBpmnModel
53 54 // TODO @yunai:注释需要完善下;
  55 +
54 56 /**
55 57 * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善)
56 58 *
... ... @@ -59,11 +61,12 @@ public class SimpleModelUtils {
59 61 * @param simpleModelNode 仿钉钉流程设计模型数据结构
60 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 65 BpmnModel bpmnModel = new BpmnModel();
64 66 bpmnModel.setTargetNamespace(BPMN2_NAMESPACE); // TODO @jason:待定:是不是搞个自定义的 namespace;
65 67 // TODO 芋艿:后续在 review
66   - // 不加这个 解析 Message 会报 NPE 异常
  68 + // @芋艿 这个 Message 可以去掉 暂时用不上
  69 + // 不加这个 解析 Message 会报 NPE 异常 .
67 70 Message rejectPostProcessMsg = new Message();
68 71 rejectPostProcessMsg.setName(REJECT_POST_PROCESS_MESSAGE_NAME);
69 72 bpmnModel.addMessage(rejectPostProcessMsg);
... ... @@ -76,13 +79,9 @@ public class SimpleModelUtils {
76 79  
77 80 // 前端模型数据结构
78 81 // 从 SimpleModel 构建 FlowNode 并添加到 Main Process
79   - buildAndAddBpmnFlowNode(simpleModelNode, process);
  82 + traverseNodeToBuildFlowNode(simpleModelNode, process);
80 83 // 找到 end event
81 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 86 // 构建并添加节点之间的连线 Sequence Flow
88 87 buildAndAddBpmnSequenceFlow(process, simpleModelNode, endEvent.getId());
... ... @@ -202,95 +201,100 @@ public class SimpleModelUtils {
202 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 211 return;
212 212 }
213   - BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType());
  213 + BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
214 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 240 switch (nodeType) {
217 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 245 break;
222 246 }
223 247 case USER_TASK: {
224 248 // TODO @jason:这个,搞成一个 buildUserTask,然后把下面这 2 种节点,搞在一起实现类;这样 buildNode 里面可以更简洁;
225 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 254 if (userTaskConfig.getTimeoutHandler() != null && userTaskConfig.getTimeoutHandler().getEnable()) {
231 255 // 添加用户任务的 Timer Boundary Event, 用于任务的超时处理
232 256 BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler());
233   - mainProcess.addFlowElement(boundaryEvent);
  257 + //process.addFlowElement(boundaryEvent);
  258 + list.add(boundaryEvent);
234 259 }
235 260 break;
236 261 }
237 262 case COPY_TASK: {
238   - ServiceTask serviceTask = buildBpmnServiceTask(simpleModelNode);
239   - mainProcess.addFlowElement(serviceTask);
  263 + ServiceTask serviceTask = buildServiceTask(node);
  264 + list.add(serviceTask);
240 265 break;
241 266 }
242 267 case EXCLUSIVE_GATEWAY: {
243   - ExclusiveGateway exclusiveGateway = buildBpmnExclusiveGateway(simpleModelNode);
244   - mainProcess.addFlowElement(exclusiveGateway);
  268 + ExclusiveGateway exclusiveGateway = buildExclusiveGateway(node);
  269 + list.add(exclusiveGateway);
245 270 break;
246 271 }
247 272 case PARALLEL_GATEWAY_FORK:
248 273 case PARALLEL_GATEWAY_JOIN: {
249   - ParallelGateway parallelGateway = buildBpmnParallelGateway(simpleModelNode);
250   - mainProcess.addFlowElement(parallelGateway);
  274 + ParallelGateway parallelGateway = buildParallelGateway(node);
  275 + list.add(parallelGateway);
251 276 break;
252 277 }
253 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 281 break;
257 282 }
258 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 286 break;
262 287 }
263 288 case END_EVENT: {
264   - EndEvent endEvent = buildBpmnEndEvent(simpleModelNode);
265   - mainProcess.addFlowElement(endEvent);
  289 + EndEvent endEvent = buildEndEvent(node);
  290 + list.add(endEvent);
266 291 break;
267 292 }
268 293 default: {
269 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 300 private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) {
... ... @@ -315,7 +319,7 @@ public class SimpleModelUtils {
315 319 return boundaryEvent;
316 320 }
317 321  
318   - private static ParallelGateway buildBpmnParallelGateway(BpmSimpleModelNodeVO node) {
  322 + private static ParallelGateway buildParallelGateway(BpmSimpleModelNodeVO node) {
319 323 ParallelGateway parallelGateway = new ParallelGateway();
320 324 parallelGateway.setId(node.getId());
321 325 // TODO @jason:setName
... ... @@ -324,7 +328,7 @@ public class SimpleModelUtils {
324 328 return parallelGateway;
325 329 }
326 330  
327   - private static ServiceTask buildBpmnServiceTask(BpmSimpleModelNodeVO node) {
  331 + private static ServiceTask buildServiceTask(BpmSimpleModelNodeVO node) {
328 332 ServiceTask serviceTask = new ServiceTask();
329 333 serviceTask.setId(node.getId());
330 334 serviceTask.setName(node.getName());
... ... @@ -340,7 +344,8 @@ public class SimpleModelUtils {
340 344 // 添加表单字段权限属性元素
341 345 // TODO @芋艿:这块关注下哈;
342 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 349 addFormFieldsPermission(fieldsPermissions, serviceTask);
345 350 return serviceTask;
346 351 }
... ... @@ -354,7 +359,7 @@ public class SimpleModelUtils {
354 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 363 Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
359 364 ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
360 365 exclusiveGateway.setId(node.getId());
... ... @@ -367,7 +372,7 @@ public class SimpleModelUtils {
367 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 376 InclusiveGateway inclusiveGateway = new InclusiveGateway();
372 377 inclusiveGateway.setId(node.getId());
373 378 // TODO @jason:这里是不是 setName 哈;
... ... @@ -483,7 +488,7 @@ public class SimpleModelUtils {
483 488  
484 489 // ========== 各种 build 节点的方法 ==========
485 490  
486   - private static StartEvent buildBpmnStartEvent(BpmSimpleModelNodeVO node) {
  491 + private static StartEvent buildStartEvent(BpmSimpleModelNodeVO node) {
487 492 StartEvent startEvent = new StartEvent();
488 493 startEvent.setId(node.getId());
489 494 startEvent.setName(node.getName());
... ... @@ -492,7 +497,7 @@ public class SimpleModelUtils {
492 497 return startEvent;
493 498 }
494 499  
495   - private static EndEvent buildBpmnEndEvent(BpmSimpleModelNodeVO node) {
  500 + private static EndEvent buildEndEvent(BpmSimpleModelNodeVO node) {
496 501 EndEvent endEvent = new EndEvent();
497 502 endEvent.setId(node.getId());
498 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 231 throw exception(MODEL_NOT_EXISTS);
232 232 }
233 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 235 // 2.1 保存 Bpmn XML
236 236 saveModelBpmnXml(model.getId(), StrUtil.utf8Bytes(BpmnModelUtils.getBpmnXml(bpmnModel)));
237 237 // 2.2 保存 JSON 数据
... ...