Bläddra i källkod

【代码优化】工作流:进一步完善 SimpleModelUtils、BpmnModelUtils 的注释,提升可读性!

YunaiV 7 månader sedan
förälder
incheckning
1c78cdc26e

+ 1 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java

@@ -87,6 +87,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
     }
 
     @Override
+    @SuppressWarnings("PatternVariableCanBeUsed")
     protected void timerFired(FlowableEngineEntityEvent event) {
         // 1.1 只处理 BoundaryEvent 边界计时时间
         String processDefinitionId = event.getProcessDefinitionId();

+ 124 - 26
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java

@@ -9,6 +9,9 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.framework.common.util.string.StrUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskApproveTypeEnum;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignEmptyHandlerTypeEnum;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignStartUserHandlerTypeEnum;
 import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
 import com.google.common.collect.Maps;
@@ -24,10 +27,18 @@ import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_N
 import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_PREFIX;
 
 /**
- * 流程模型转操作工具类
+ * BPMN Model 操作工具类。目前分成三部分:
+ *
+ * 1. BPMN 修改 + 解析元素相关的方法
+ * 2. BPM 简单查找相关的方法
+ * 3. BPM 复杂遍历相关的方法
+ *
+ * @author 芋道源码
  */
 public class BpmnModelUtils {
 
+    // ========== BPMN 修改 + 解析元素相关的方法 ==========
+
     public static void addExtensionElement(FlowElement element, String name, String value) {
         if (value == null) {
             return;
@@ -63,6 +74,21 @@ public class BpmnModelUtils {
         element.addExtensionElement(extensionElement);
     }
 
+    /**
+     * 解析扩展元素
+     *
+     * @param flowElement 节点
+     * @param elementName 元素名称
+     * @return 扩展元素
+     */
+    public static String parseExtensionElement(FlowElement flowElement, String elementName) {
+        if (flowElement == null) {
+            return null;
+        }
+        ExtensionElement element = CollUtil.getFirst(flowElement.getExtensionElements().get(elementName));
+        return element != null ? element.getElementText() : null;
+    }
+
     /**
      * 给节点添加候选人元素
      *
@@ -79,7 +105,7 @@ public class BpmnModelUtils {
     /**
      * 解析候选人策略
      *
-     * @param userTask 节点
+     * @param userTask 任务节点
      * @return 候选人策略
      */
     public static Integer parseCandidateStrategy(FlowElement userTask) {
@@ -93,6 +119,12 @@ public class BpmnModelUtils {
         return candidateStrategy;
     }
 
+    /**
+     * 解析候选人参数
+     *
+     * @param userTask 任务节点
+     * @return 候选人参数
+     */
     public static String parseCandidateParam(FlowElement userTask) {
         String candidateParam = userTask.getAttributeValue(
                 BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM);
@@ -103,10 +135,23 @@ public class BpmnModelUtils {
         return candidateParam;
     }
 
+    /**
+     * 解析审批类型
+     *
+     * @see BpmUserTaskApproveTypeEnum
+     * @param userTask 任务节点
+     * @return 审批类型
+     */
     public static Integer parseApproveType(FlowElement userTask) {
         return NumberUtils.parseInt(parseExtensionElement(userTask, BpmnModelConstants.USER_TASK_APPROVE_TYPE));
     }
 
+    /**
+     * 添加任务拒绝处理元素
+     *
+     * @param rejectHandler 任务拒绝处理
+     * @param userTask 任务节点
+     */
     public static void addTaskRejectElements(BpmSimpleModelNodeVO.RejectHandler rejectHandler, UserTask userTask) {
         if (rejectHandler == null) {
             return;
@@ -115,15 +160,34 @@ public class BpmnModelUtils {
         addExtensionElement(userTask, USER_TASK_REJECT_RETURN_TASK_ID, rejectHandler.getReturnNodeId());
     }
 
+    /**
+     * 解析任务拒绝处理类型
+     *
+     * @param userTask 任务节点
+     * @return 任务拒绝处理类型
+     */
     public static BpmUserTaskRejectHandlerType parseRejectHandlerType(FlowElement userTask) {
         Integer rejectHandlerType = NumberUtils.parseInt(parseExtensionElement(userTask, USER_TASK_REJECT_HANDLER_TYPE));
         return BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType);
     }
 
+    /**
+     * 解析任务拒绝返回任务节点 ID
+     *
+     * @param flowElement 任务节点
+     * @return 任务拒绝返回任务节点 ID
+     */
     public static String parseReturnTaskId(FlowElement flowElement) {
         return parseExtensionElement(flowElement, USER_TASK_REJECT_RETURN_TASK_ID);
     }
 
+    /**
+     * 给节点添加用户任务的审批人与发起人相同时,处理类型枚举
+     *
+     * @see BpmUserTaskAssignStartUserHandlerTypeEnum
+     * @param assignStartUserHandlerType 发起人处理类型
+     * @param userTask 任务节点
+     */
     public static void addAssignStartUserHandlerType(Integer assignStartUserHandlerType, UserTask userTask) {
         if (assignStartUserHandlerType == null) {
             return;
@@ -131,6 +195,13 @@ public class BpmnModelUtils {
         addExtensionElement(userTask, USER_TASK_ASSIGN_START_USER_HANDLER_TYPE, assignStartUserHandlerType.toString());
     }
 
+    /**
+     * 给节点添加用户任务的审批人为空时,处理类型枚举
+     *
+     * @see BpmUserTaskAssignEmptyHandlerTypeEnum
+     * @param emptyHandler 空处理
+     * @param userTask 任务节点
+     */
     public static void addAssignEmptyHandlerType(BpmSimpleModelNodeVO.AssignEmptyHandler emptyHandler, UserTask userTask) {
         if (emptyHandler == null) {
             return;
@@ -139,26 +210,36 @@ public class BpmnModelUtils {
         addExtensionElement(userTask, USER_TASK_ASSIGN_USER_IDS, StrUtil.join(",", emptyHandler.getUserIds()));
     }
 
+    /**
+     * 解析用户任务的审批人与发起人相同时,处理类型枚举
+     *
+     * @param userTask 任务节点
+     * @return 处理类型枚举
+     */
     public static Integer parseAssignStartUserHandlerType(FlowElement userTask) {
         return NumberUtils.parseInt(parseExtensionElement(userTask, USER_TASK_ASSIGN_START_USER_HANDLER_TYPE));
     }
 
+    /**
+     * 解析用户任务的审批人为空时,处理类型枚举
+     *
+     * @param userTask 任务节点
+     * @return 处理类型枚举
+     */
     public static Integer parseAssignEmptyHandlerType(FlowElement userTask) {
         return NumberUtils.parseInt(parseExtensionElement(userTask, USER_TASK_ASSIGN_EMPTY_HANDLER_TYPE));
     }
 
+    /**
+     * 解析用户任务的审批人为空时,处理用户 ID 数组
+     *
+     * @param userTask 任务节点
+     * @return 处理用户 ID 数组
+     */
     public static List<Long> parseAssignEmptyHandlerUserIds(FlowElement userTask) {
         return StrUtils.splitToLong(parseExtensionElement(userTask, USER_TASK_ASSIGN_USER_IDS), ",");
     }
 
-    public static String parseExtensionElement(FlowElement flowElement, String elementName) {
-        if (flowElement == null) {
-            return null;
-        }
-        ExtensionElement element = CollUtil.getFirst(flowElement.getExtensionElements().get(elementName));
-        return element != null ? element.getElementText() : null;
-    }
-
     /**
      * 给节点添加表单字段权限元素
      *
@@ -217,6 +298,13 @@ public class BpmnModelUtils {
         }
     }
 
+    /**
+     * 解析操作按钮设置
+     *
+     * @param bpmnModel bpmnModel 对象
+     * @param flowElementId 元素 ID
+     * @return 操作按钮设置
+     */
     public static Map<Integer, BpmTaskRespVO.OperationButtonSetting> parseButtonsSetting(BpmnModel bpmnModel, String flowElementId) {
         FlowElement flowElement = getFlowElementById(bpmnModel, flowElementId);
         if (flowElement == null) {
@@ -226,7 +314,7 @@ public class BpmnModelUtils {
         if (CollUtil.isEmpty(extensionElements)) {
             return null;
         }
-        Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonSettings = MapUtil.newHashMap(16);
+        Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonSettings = Maps.newHashMapWithExpectedSize(extensionElements.size());
         extensionElements.forEach(element -> {
             String id = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, BUTTON_SETTING_ELEMENT_ID_ATTRIBUTE);
             String displayName = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, BUTTON_SETTING_ELEMENT_DISPLAY_NAME_ATTRIBUTE);
@@ -239,6 +327,23 @@ public class BpmnModelUtils {
         return buttonSettings;
     }
 
+    /**
+     * 解析边界事件扩展元素
+     *
+     * @param boundaryEvent 边界事件
+     * @param customElement 元素
+     * @return 扩展元素
+     */
+    public static String parseBoundaryEventExtensionElement(BoundaryEvent boundaryEvent, String customElement) {
+        if (boundaryEvent == null) {
+            return null;
+        }
+        ExtensionElement extensionElement = CollUtil.getFirst(boundaryEvent.getExtensionElements().get(customElement));
+        return Optional.ofNullable(extensionElement).map(ExtensionElement::getElementText).orElse(null);
+    }
+
+    // ========== BPM 简单查找相关的方法 ==========
+
     /**
      * 根据节点,获取入口连线
      *
@@ -284,15 +389,14 @@ public class BpmnModelUtils {
      * @param clazz 指定元素。例如说,{@link UserTask}、{@link Gateway} 等等
      * @return 元素们
      */
+    @SuppressWarnings("unchecked")
     public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
         List<T> result = new ArrayList<>();
-        model.getProcesses().forEach(process -> {
-            process.getFlowElements().forEach(flowElement -> {
-                if (flowElement.getClass().isAssignableFrom(clazz)) {
-                    result.add((T) flowElement);
-                }
-            });
-        });
+        model.getProcesses().forEach(process -> process.getFlowElements().forEach(flowElement -> {
+            if (flowElement.getClass().isAssignableFrom(clazz)) {
+                result.add((T) flowElement);
+            }
+        }));
         return result;
     }
 
@@ -337,7 +441,7 @@ public class BpmnModelUtils {
         return StrUtil.utf8Str(bpmnBytes);
     }
 
-    // ========== 遍历相关的方法 ==========
+    // ========== BPMN 复杂遍历相关的方法 ==========
 
     /**
      * 找到 source 节点之前的所有用户任务节点
@@ -441,6 +545,7 @@ public class BpmnModelUtils {
      * @param visitedElements 已经经过的连线的 ID,用于判断线路是否重复
      * @return 结果
      */
+    @SuppressWarnings("BooleanMethodIsAlwaysInverted")
     public static boolean isSequentialReachable(FlowElement source, FlowElement target, Set<String> visitedElements) {
         visitedElements = visitedElements == null ? new HashSet<>() : visitedElements;
         // 不能是开始事件和子流程
@@ -551,11 +656,4 @@ public class BpmnModelUtils {
         return userTaskList;
     }
 
-    public static String parseBoundaryEventExtensionElement(BoundaryEvent boundaryEvent, String customElement) {
-        if (boundaryEvent == null) {
-            return null;
-        }
-        ExtensionElement extensionElement = CollUtil.getFirst(boundaryEvent.getExtensionElements().get(customElement));
-        return Optional.ofNullable(extensionElement).map(ExtensionElement::getElementText).orElse(null);
-    }
 }

+ 8 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java

@@ -25,6 +25,9 @@ import static java.util.Arrays.asList;
 /**
  * 仿钉钉/飞书的模型相关的工具方法
  *
+ * 1. 核心的逻辑实现,可见 {@link #buildBpmnModel(String, String, BpmSimpleModelNodeVO)} 方法
+ * 2. 所有的 BpmSimpleModelNodeVO 转换成 BPMN FlowNode 元素,可见 {@link NodeConvert} 实现类
+ *
  * @author jason
  */
 public class SimpleModelUtils {
@@ -41,6 +44,11 @@ public class SimpleModelUtils {
     /**
      * 仿钉钉流程设计模型数据结构(json)转换成 Bpmn Model
      *
+     * 整体逻辑如下:
+     * 1. 创建:BpmnModel、Process 对象
+     * 2. 转换:将 BpmSimpleModelNodeVO 转换成 BPMN FlowNode 元素
+     * 3. 连接:构建并添加节点之间的连线 Sequence Flow
+     *
      * @param processId       流程标识
      * @param processName     流程名称
      * @param simpleModelNode 仿钉钉流程设计模型数据结构