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 拓扑推导工具(back/jump/next/prev 等接口的核心)。
|
* 由黑盒 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;
|
}
|
}
|