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

This commit is contained in:
YunaiV 2024-10-19 16:10:45 +08:00
parent 23b011b6f9
commit 1c78cdc26e
3 changed files with 133 additions and 26 deletions

View File

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

View File

@ -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);
}
}

View File

@ -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. 创建BpmnModelProcess 对象
* 2. 转换 BpmSimpleModelNodeVO 转换成 BPMN FlowNode 元素
* 3. 连接构建并添加节点之间的连线 Sequence Flow
*
* @param processId 流程标识
* @param processName 流程名称
* @param simpleModelNode 仿钉钉流程设计模型数据结构