From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-flow-engine/src/main/java/jnpf/workflow/flowable/util/FlowableUtil.java |  250 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 250 insertions(+), 0 deletions(-)

diff --git a/jnpf-flow-engine/src/main/java/jnpf/workflow/flowable/util/FlowableUtil.java b/jnpf-flow-engine/src/main/java/jnpf/workflow/flowable/util/FlowableUtil.java
new file mode 100644
index 0000000..7163f08
--- /dev/null
+++ b/jnpf-flow-engine/src/main/java/jnpf/workflow/flowable/util/FlowableUtil.java
@@ -0,0 +1,250 @@
+package jnpf.workflow.flowable.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import org.flowable.bpmn.model.EndEvent;
+import org.flowable.bpmn.model.FlowElement;
+import org.flowable.bpmn.model.FlowNode;
+import org.flowable.bpmn.model.Gateway;
+import org.flowable.bpmn.model.SequenceFlow;
+import org.flowable.bpmn.model.StartEvent;
+import org.flowable.bpmn.model.SubProcess;
+import org.flowable.bpmn.model.UserTask;
+
+import cn.hutool.core.collection.CollectionUtil;
+import jnpf.workflow.common.model.vo.FlowVo;
+
+/**
+ * BPMN 鎷撴墤鎺ㄥ宸ュ叿锛坆ack/jump/next/prev 绛夋帴鍙g殑鏍稿績锛夈��
+ * 鐢遍粦鐩� jar 鍙嶇紪璇戦�愯淇濈湡杩樺師锛屽嬁鍋�"椤烘墜浼樺寲"銆�
+ */
+public class FlowableUtil {
+
+    public static Collection<FlowElement> getAllElements(Collection<FlowElement> flowElements, Collection<FlowElement> allElements) {
+        allElements = allElements == null ? new ArrayList<>() : allElements;
+        for (FlowElement flowElement : flowElements) {
+            allElements.add(flowElement);
+            if (!(flowElement instanceof SubProcess)) {
+                continue;
+            }
+            allElements = getAllElements(((SubProcess) flowElement).getFlowElements(), allElements);
+        }
+        return allElements;
+    }
+
+    public static List<SequenceFlow> getElementIncomingFlows(FlowElement element) {
+        List<SequenceFlow> flows = null;
+        if (element instanceof FlowNode) {
+            flows = ((FlowNode) element).getIncomingFlows();
+        }
+        return flows;
+    }
+
+    public static List<SequenceFlow> getElementOutgoingFlows(FlowElement element) {
+        List<SequenceFlow> flows = null;
+        if (element instanceof FlowNode) {
+            flows = ((FlowNode) element).getOutgoingFlows();
+        }
+        return flows;
+    }
+
+    public static List<String> getPassActs(FlowElement source, Set<String> passFlows, List<String> passActs) {
+        passFlows = passFlows == null ? new HashSet<>() : passFlows;
+        passActs = passActs == null ? new ArrayList<>() : passActs;
+        List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
+        if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
+            for (SequenceFlow sequenceFlow : sequenceFlows) {
+                if (passFlows.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                passFlows.add(sequenceFlow.getId());
+                if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
+                    passActs.add(sequenceFlow.getSourceFlowElement().getId());
+                }
+                if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
+                    passActs.add(sequenceFlow.getSourceFlowElement().getId());
+                    continue;
+                }
+                getPassActs(sequenceFlow.getSourceFlowElement(), passFlows, passActs);
+            }
+        }
+        return passActs;
+    }
+
+    public static List<UserTask> getChildUserTasks(FlowElement source, List<String> runTaskKeyList, Set<String> passFlows, List<UserTask> userTasks) {
+        passFlows = passFlows == null ? new HashSet<>() : passFlows;
+        userTasks = userTasks == null ? new ArrayList<>() : userTasks;
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+        if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
+            for (SequenceFlow sequenceFlow : sequenceFlows) {
+                if (passFlows.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                passFlows.add(sequenceFlow.getId());
+                if (sequenceFlow.getTargetFlowElement() instanceof UserTask && runTaskKeyList.contains(sequenceFlow.getTargetFlowElement().getId())) {
+                    userTasks.add((UserTask) sequenceFlow.getTargetFlowElement());
+                    continue;
+                }
+                if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
+                    FlowElement flowElement = (FlowElement) ((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0];
+                    List<UserTask> tasks = getChildUserTasks(flowElement, runTaskKeyList, passFlows, null);
+                    if (!tasks.isEmpty()) {
+                        userTasks.addAll(tasks);
+                        continue;
+                    }
+                }
+                getChildUserTasks(sequenceFlow.getTargetFlowElement(), runTaskKeyList, passFlows, userTasks);
+            }
+        }
+        return userTasks;
+    }
+
+    public static List<String> getParentActs(FlowElement source, Set<String> passFlows, List<String> parentActs) {
+        passFlows = passFlows == null ? new HashSet<>() : passFlows;
+        parentActs = parentActs == null ? new ArrayList<>() : parentActs;
+        List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
+        if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
+            for (SequenceFlow sequenceFlow : sequenceFlows) {
+                if (passFlows.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                passFlows.add(sequenceFlow.getId());
+                if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
+                    parentActs.add(sequenceFlow.getSourceFlowElement().getId());
+                    continue;
+                }
+                if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
+                    parentActs.add(sequenceFlow.getSourceFlowElement().getId());
+                    continue;
+                }
+                getParentActs(sequenceFlow.getSourceFlowElement(), passFlows, parentActs);
+            }
+        }
+        return parentActs;
+    }
+
+    public static List<UserTask> getNextUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
+        hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
+        userTaskList = Optional.ofNullable(userTaskList).orElse(new ArrayList<>());
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+        if (null != sequenceFlows) {
+            for (SequenceFlow sequenceFlow : sequenceFlows) {
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                hasSequenceFlow.add(sequenceFlow.getId());
+                FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
+                if (targetFlowElement instanceof UserTask) {
+                    userTaskList.add((UserTask) targetFlowElement);
+                    continue;
+                }
+                getNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList);
+            }
+        }
+        return userTaskList;
+    }
+
+    public static List<String> getAfter(FlowElement source, Set<String> hasSequenceFlow, List<String> list) {
+        hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
+        list = Optional.ofNullable(list).orElse(new ArrayList<>());
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+        if (null != sequenceFlows) {
+            for (SequenceFlow sequenceFlow : sequenceFlows) {
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                hasSequenceFlow.add(sequenceFlow.getId());
+                FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
+                if (targetFlowElement instanceof UserTask) {
+                    list.add(targetFlowElement.getId());
+                } else if (targetFlowElement instanceof EndEvent) {
+                    list.add(targetFlowElement.getId());
+                    continue;
+                }
+                getAfter(targetFlowElement, hasSequenceFlow, list);
+            }
+        }
+        return list;
+    }
+
+    public static List<SequenceFlow> getOutFlowsWithGateway(FlowElement source, List<SequenceFlow> flows) {
+        flows = flows == null ? new ArrayList<>() : flows;
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+        if (null != sequenceFlows) {
+            for (SequenceFlow sequenceFlow : sequenceFlows) {
+                flows.add(sequenceFlow);
+                FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
+                if (targetFlowElement instanceof UserTask || !(targetFlowElement instanceof Gateway)) {
+                    continue;
+                }
+                Gateway gateway = (Gateway) targetFlowElement;
+                List<SequenceFlow> outgoingFlows = gateway.getOutgoingFlows();
+                flows.addAll(outgoingFlows);
+                getOutFlowsWithGateway(gateway, flows);
+            }
+        }
+        return flows;
+    }
+
+    public static List<FlowVo> getOutFlows(FlowElement source, List<FlowVo> flows) {
+        flows = flows == null ? new ArrayList<>() : flows;
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+        if (null != sequenceFlows) {
+            for (SequenceFlow sequenceFlow : sequenceFlows) {
+                FlowVo vo = new FlowVo();
+                vo.setKey(sequenceFlow.getId());
+                FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
+                if (targetFlowElement instanceof Gateway) {
+                    Gateway gateway = (Gateway) targetFlowElement;
+                    List<FlowVo> list = getOutFlows(gateway, null);
+                    vo.setChildren(list);
+                }
+                flows.add(vo);
+            }
+        }
+        return flows;
+    }
+
+    public static List<String> getBefore(FlowElement source, Set<String> passFlows, List<String> keys) {
+        passFlows = passFlows == null ? new HashSet<>() : passFlows;
+        keys = keys == null ? new ArrayList<>() : keys;
+        List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
+        if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
+            for (SequenceFlow sequenceFlow : sequenceFlows) {
+                if (passFlows.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                passFlows.add(sequenceFlow.getId());
+                keys.add(sequenceFlow.getSourceFlowElement().getId());
+                if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
+                    continue;
+                }
+                getBefore(sequenceFlow.getSourceFlowElement(), passFlows, keys);
+            }
+        }
+        return keys;
+    }
+
+    public static String getTaskKeyAfterFlow(FlowElement source) {
+        if (source instanceof SequenceFlow) {
+            SequenceFlow sequenceFlow = (SequenceFlow) source;
+            FlowElement target = sequenceFlow.getTargetFlowElement();
+            if (target instanceof Gateway) {
+                List<SequenceFlow> outgoingFlows = ((Gateway) target).getOutgoingFlows();
+                if (CollectionUtil.isNotEmpty(outgoingFlows)) {
+                    SequenceFlow flow = outgoingFlows.get(0);
+                    return getTaskKeyAfterFlow(flow);
+                }
+            }
+            if (target instanceof UserTask) {
+                return target.getId();
+            }
+        }
+        return null;
+    }
+}

--
Gitblit v1.8.0