<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
</dependency>
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.util.io.StringStreamSource;
import java.util.*;
public class BpmnModelUtil {
private static final BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
public static BpmnModel getBpmnModel(String xml) {
return bpmnXMLConverter.convertToBpmnModel(new StringStreamSource(xml), false, false);
}
@Deprecated
public static String getBpmnXmlStr(BpmnModel bpmnModel) {
return StrUtil.utf8Str(getBpmnXml(bpmnModel));
}
@Deprecated
public static byte[] getBpmnXml(BpmnModel bpmnModel) {
return bpmnXMLConverter.convertToXML(bpmnModel);
}
public static List<SequenceFlow> getElementIncomingFlows(FlowElement source) {
List<SequenceFlow> sequenceFlows = new ArrayList<>();
if (source instanceof FlowNode) {
sequenceFlows = ((FlowNode) source).getIncomingFlows();
}
return sequenceFlows;
}
public static List<SequenceFlow> getElementOutgoingFlows(FlowElement source) {
List<SequenceFlow> sequenceFlows = new ArrayList<>();
if (source instanceof FlowNode) {
sequenceFlows = ((FlowNode) source).getOutgoingFlows();
}
return sequenceFlows;
}
public static StartEvent getStartEvent(BpmnModel model) {
Process process = model.getMainProcess();
FlowElement startElement = process.getInitialFlowElement();
if (startElement instanceof StartEvent) {
return (StartEvent) startElement;
}
return getStartEvent(process.getFlowElements());
}
public static StartEvent getStartEvent(Collection<FlowElement> flowElements) {
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof StartEvent) {
return (StartEvent) flowElement;
}
}
return null;
}
public static EndEvent getEndEvent(BpmnModel model) {
Process process = model.getMainProcess();
return getEndEvent(process.getFlowElements());
}
public static EndEvent getEndEvent(Collection<FlowElement> flowElements) {
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof EndEvent) {
return (EndEvent) flowElement;
}
}
return null;
}
public static UserTask getUserTaskByKey(BpmnModel model, String taskKey) {
Process process = model.getMainProcess();
FlowElement flowElement = process.getFlowElement(taskKey);
if (flowElement instanceof UserTask) {
return (UserTask) flowElement;
}
return null;
}
public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) {
Process process = model.getMainProcess();
return process.getFlowElement(flowElementId);
}
public static String getFormKey(FlowElement flowElement) {
if (flowElement != null) {
if (flowElement instanceof StartEvent) {
return ((StartEvent) flowElement).getFormKey();
} else if (flowElement instanceof UserTask) {
return ((UserTask) flowElement).getFormKey();
}
}
return null;
}
public static String getStartEventAttributeValue(BpmnModel model, String name) {
StartEvent startEvent = getStartEvent(model);
return getElementAttributeValue(startEvent, name);
}
public static String getEndEventAttributeValue(BpmnModel model, String name) {
EndEvent endEvent = getEndEvent(model);
return getElementAttributeValue(endEvent, name);
}
public static String getUserTaskAttributeValue(BpmnModel model, String taskKey, String name) {
UserTask userTask = getUserTaskByKey(model, taskKey);
return getElementAttributeValue(userTask, name);
}
public static String getElementAttributeValue(BaseElement baseElement, String name) {
if (baseElement != null) {
List<ExtensionAttribute> attributes = baseElement.getAttributes().get(name);
if (attributes != null && !attributes.isEmpty()) {
attributes.iterator().next().getValue();
Iterator<ExtensionAttribute> attrIterator = attributes.iterator();
if(attrIterator.hasNext()) {
ExtensionAttribute attribute = attrIterator.next();
return attribute.getValue();
}
}
}
return null;
}
public static boolean isMultiInstance(BpmnModel model, String taskKey) {
UserTask userTask = getUserTaskByKey(model, taskKey);
if (ObjectUtil.isNotNull(userTask)) {
return userTask.hasMultiInstanceLoopCharacteristics();
}
return false;
}
public static Collection<UserTask> getAllUserTaskEvent(BpmnModel model) {
Process process = model.getMainProcess();
Collection<FlowElement> flowElements = process.getFlowElements();
return getAllUserTaskEvent(flowElements, null);
}
public static Collection<UserTask> getAllUserTaskEvent(Collection<FlowElement> flowElements, Collection<UserTask> allElements) {
allElements = allElements == null ? new ArrayList<>() : allElements;
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof UserTask) {
allElements.add((UserTask) flowElement);
}
if (flowElement instanceof SubProcess) {
allElements = getAllUserTaskEvent(((SubProcess) flowElement).getFlowElements(), allElements);
}
}
return allElements;
}
public static List<UserTask> findNextUserTasks(FlowElement source) {
return findNextUserTasks(source, null, null);
}
public static List<UserTask> findNextUserTasks(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 (!sequenceFlows.isEmpty()) {
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);
} else {
findNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList);
}
}
}
return userTaskList;
}
public static boolean isSequentialReachable(FlowElement source, FlowElement target, Set<String> visitedElements) {
visitedElements = visitedElements == null ? new HashSet<>() : visitedElements;
if (source instanceof StartEvent && isInEventSubprocess(source)) {
return false;
}
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
if (sequenceFlows != null && sequenceFlows.size() > 0) {
for (SequenceFlow sequenceFlow: sequenceFlows) {
if (visitedElements.contains(sequenceFlow.getId())) {
continue;
}
visitedElements.add(sequenceFlow.getId());
FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
if (target.getId().equals(sourceFlowElement.getId())) {
continue;
}
if (sourceFlowElement instanceof ParallelGateway) {
return false;
}
boolean isSequential = isSequentialReachable(sourceFlowElement, target, visitedElements);
if (!isSequential) {
return false;
}
}
}
return true;
}
protected static boolean isInEventSubprocess(FlowElement flowElement) {
FlowElementsContainer flowElementsContainer = flowElement.getParentContainer();
while (flowElementsContainer != null) {
if (flowElementsContainer instanceof EventSubProcess) {
return true;
}
if (flowElementsContainer instanceof FlowElement) {
flowElementsContainer = ((FlowElement) flowElementsContainer).getParentContainer();
} else {
flowElementsContainer = null;
}
}
return false;
}
}