From 1c78cdc26e714e636354f3ec2403f7c12717ee07 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 19 Oct 2024 16:10:45 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E3=80=91=E5=B7=A5=E4=BD=9C=E6=B5=81=EF=BC=9A=E8=BF=9B=E4=B8=80?= =?UTF-8?q?=E6=AD=A5=E5=AE=8C=E5=96=84=20SimpleModelUtils=E3=80=81BpmnMode?= =?UTF-8?q?lUtils=20=E7=9A=84=E6=B3=A8=E9=87=8A=EF=BC=8C=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E5=8F=AF=E8=AF=BB=E6=80=A7=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/listener/BpmTaskEventListener.java | 1 + .../flowable/core/util/BpmnModelUtils.java | 150 +++++++++++++++--- .../flowable/core/util/SimpleModelUtils.java | 8 + 3 files changed, 133 insertions(+), 26 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java index bece6740e..c0e61c27d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java +++ b/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(); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index 4948a7d55..59c044759 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/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 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 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 buttonSettings = MapUtil.newHashMap(16); + Map 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 List getBpmnModelElements(BpmnModel model, Class clazz) { List 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 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); - } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 0069bdb29..283e9dd7e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/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 仿钉钉流程设计模型数据结构