
cn.lzgabel.util.Util Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bpmn-auto-layout Show documentation
Show all versions of bpmn-auto-layout Show documentation
Tools for auto layout bpmn files
package cn.lzgabel.util;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.Activity;
import org.activiti.bpmn.model.Artifact;
import org.activiti.bpmn.model.Association;
import org.activiti.bpmn.model.BoundaryEvent;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.SubProcess;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.filter.ElementFilter;
import org.jdom2.input.DOMBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.xml.sax.SAXException;
public class Util {
static boolean firstSortDone = false;
static List L;
static List B;
static BpmnModel model;
private static void safeXMLFile(String filename, Document document) throws IOException {
XMLOutputter xmlOutput = new XMLOutputter();
xmlOutput.setFormat(Format.getPrettyFormat());
xmlOutput.output(document, new FileWriter(filename));
}
public static List topologicalSortNodes(Collection flowNodes, BpmnModel model) {
Util.model = model;
L = new ArrayList();
B = new ArrayList();
Collection flowNodeList = new ArrayList<>();
flowNodeList.addAll(flowNodes);
List S = new ArrayList<>();
// algorithm from kitzmann09
while (!flowNodeList.isEmpty()) {
S.clear();
for (FlowNode element : flowNodeList) {
if (element.getIncomingFlows().size() == 0
|| allIncomingElementsAlreadyAdded(element.getIncomingFlows(), L))
S.add(element);
}
if (!S.isEmpty()) {
while (!S.isEmpty()) {
// ordinary top-sort
FlowNode n = S.get(0);
flowNodeList.remove(S.remove(0));
L.add(n);
if (n instanceof Activity) {
Activity activity = (Activity) n;
List boundaryEvents = activity.getBoundaryEvents();
L.addAll(boundaryEvents);
for (BoundaryEvent boundaryEvent : boundaryEvents) {
String boundaryEventChildRef = getBoundaryEventChildRef(boundaryEvent, model);
FlowNode boundaryEventChildNode = (FlowNode) model.getFlowElement(boundaryEventChildRef);
L.add(boundaryEventChildNode);
flowNodeList.remove(boundaryEventChildNode);
}
}
}
} else {
FlowNode J = null;
// cycle found
for (FlowNode element : flowNodeList) {
// find loop entry
if (anyIncomingElementAlreadyAdded(element.getIncomingFlows(), L)) {
J = element;
break;
}
}
assert J != null;
// process loop entry
for (SequenceFlow incomingFlow : J.getIncomingFlows()) {
if (!L.contains((FlowNode) model.getFlowElement(incomingFlow.getSourceRef())))
B.add(incomingFlow);
}
for (SequenceFlow s : B) {
swapSourceAndTarget(s);
}
}
}
for (SequenceFlow s : B) {
swapSourceAndTarget(s);
}
return L;
}
private static String getBoundaryEventChildRef(BoundaryEvent boundaryEvent, BpmnModel model) {
if (boundaryEvent.getOutgoingFlows().size() == 1)
return boundaryEvent.getOutgoingFlows().get(0).getTargetRef();
return getAssociationTargetRef(boundaryEvent, model);
}
private static String getAssociationTargetRef(BoundaryEvent boundaryEvent, BpmnModel model) {
String targetRef = searchTargetRefInProcesses(boundaryEvent, model);
if (targetRef == null)
targetRef = searchTargetRefInSubProcesses(boundaryEvent, model);
return targetRef;
}
private static String searchTargetRefInSubProcesses(BoundaryEvent boundaryEvent, BpmnModel model2) {
for (Process process : model.getProcesses()) {
for (SubProcess subprocess : process.findFlowElementsOfType(SubProcess.class)) {
for (Artifact artifact : subprocess.getArtifacts()) {
if (artifact instanceof Association) {
Association association = (Association) artifact;
if (association.getSourceRef() == boundaryEvent.getId())
return association.getTargetRef();
}
}
}
}
return null;
}
private static String searchTargetRefInProcesses(BoundaryEvent boundaryEvent, BpmnModel model) {
for (Process process : model.getProcesses()) {
for (Artifact artifact : process.getArtifacts()) {
if (artifact instanceof Association) {
Association association = (Association) artifact;
if (association.getSourceRef().equals(boundaryEvent.getId()))
return association.getTargetRef();
}
}
}
return null;
}
private static boolean anyIncomingElementAlreadyAdded(Collection incomingFlows, List L) {
for (SequenceFlow incomingFlow : incomingFlows) {
if (L.contains((FlowNode) model.getFlowElement(incomingFlow.getSourceRef())))
return true;
}
return false;
}
private static boolean allIncomingElementsAlreadyAdded(Collection incomingFlows, List L) {
for (SequenceFlow incomingFlow : incomingFlows) {
if (!L.contains((FlowNode) model.getFlowElement(incomingFlow.getSourceRef())))
return false;
}
return true;
}
private static void swapSourceAndTarget(SequenceFlow s) {
FlowNode source = (FlowNode) model.getFlowElement(s.getSourceRef());
FlowNode target = (FlowNode) model.getFlowElement(s.getTargetRef());
source.getOutgoingFlows().remove(s); // Remove outoing from loop node
source.getIncomingFlows().add(s); // Add incoming from loop node
target.getIncomingFlows().remove(s); // Remove Incoming to chosen start node
target.getOutgoingFlows().add(s); // Add Outgoing to chosen start node
s.setSourceRef(target.getId());
s.setTargetRef(source.getId());
}
public static void writeModel(BpmnModel model, String name) throws IOException, FileNotFoundException {
byte[] xml = new BpmnXMLConverter().convertToXML(model);
try (FileOutputStream out = new FileOutputStream(name)) {
out.write(xml);
}
}
public static BpmnModel readBPMFile(File file)
throws XMLStreamException, FactoryConfigurationError, FileNotFoundException {
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(file));
BpmnModel model = new BpmnXMLConverter().convertToBpmnModel(reader);
return model;
}
public static BpmnModel readFromBpmn(String xml)
throws XMLStreamException, FactoryConfigurationError {
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new ByteArrayInputStream(xml.getBytes()));
BpmnModel model = new BpmnXMLConverter().convertToBpmnModel(reader);
return model;
}
private static List getBoundaryEvents(FlowNode node) {
if (node instanceof Activity) {
Activity activity = (Activity) node;
return activity.getBoundaryEvents();
}
return null;
}
public static void addXMLElementsBackToFile(HashMap extensionMap, String filename) throws IOException, ParserConfigurationException, SAXException {
Document document = parseXMLFile(filename);
Element rootElement = document.getRootElement();
Iterator elementIterator = rootElement.getDescendants(new ElementFilter());
ArrayList parents = new ArrayList<>();
while(elementIterator.hasNext())
{
Element currentElement = elementIterator.next();
String id = currentElement.getAttributeValue("id");
if(id != null && extensionMap.containsKey(id))
{
parents.add(currentElement);
}
}
for(Element parent : parents)
{
String id = parent.getAttributeValue("id");
parent.addContent(extensionMap.get(id));
}
safeXMLFile(filename, document);
}
private static Document parseXMLFile(String filename)
throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
org.w3c.dom.Document w3cDocument = documentBuilder.parse(filename);
Document document = new DOMBuilder().build(w3cDocument);
return document;
}
public static HashMap removeAndGetElementsFromXML(String filePath, String elementName) throws ParserConfigurationException, SAXException, IOException {
HashMap elementMap = new HashMap<>();
Document document = parseXMLFile(filePath);
Element rootElement = document.getRootElement();
Iterator elementIterator = rootElement.getDescendants(new ElementFilter(elementName));
while(elementIterator.hasNext())
{
Element currentElement = elementIterator.next();
Element sedParent = (Element) currentElement.getParent();
String id = sedParent.getAttributeValue("id");
elementMap.put(id, currentElement);
}
for(Element element : elementMap.values())
element.detach();
safeXMLFile(filePath, document);
return elementMap;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy