blob: 064fa9a7633ec9bf3a875e747f379bf9b9efde94 [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*
*/
package org.eclipse.osbp.utils.vaadin.bpmn;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.osbp.utils.vaadin.bpmn.BpmnNode.BpmnShape;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class BpmnConverter {
private static Logger log = org.slf4j.LoggerFactory.getLogger(BpmnConverter.class);
private final String XMLNS_PREFIX = "xmlns:";
private final String BPMN_DIAGRAM = "bpmndi:BPMNDiagram";
private final String BPMN_PROCESS = "process";
private final String BPMN_SEQ_FLOW = "sequenceFlow";
private final String BPMN_START_EVENT = "startEvent";
private final String BPMN_MESSAGE_START_EVENT_DEF = "messageEventDefinition";
private final String BPMN_ERROR_END_EVENT_DEF = "errorEventDefinition";
private final String BPMN_END_EVENT = "endEvent";
private final String BPMN_TASK = "task";
private final String BPMN_USER_TASK = "userTask";
private final String BPMN_SCRIPT_TASK = "scriptTask";
private final String BPMN_SERVICE_TASK = "serviceTask";
private final String BPMN_RECEIVE_TASK = "receiveTask";
private final String BPMN_SEND_TASK = "sendTask";
private final String BPMN_PARALLEL_GATEWAY = "parallelGateway";
private final String BPMN_EXCLUSIVE_GATEWAY = "exclusiveGateway";
private final String BPMN_INCLUSIVE_GATEWAY = "inclusiveGateway";
private final String BPMN_CALL_ACTIVITY = "callActivity";
private Map<String, BpmnNode> bpmnComponents = new HashMap<>();
private Map<String, BpmnNode> bpmnSeqFlowComponents = new HashMap<>();
private List<String> nsTagNamePrefixes = new ArrayList<String>();
private String tagNamePrefix = "";
private StringBuilder bpmnJsCreationCode = new StringBuilder();
private NodeList emptyNodeList = new NodeList() {
@Override
public Node item(int index) {
return null;
}
@Override
public int getLength() {
return 0;
}
};
public String getTagName(String tagName) {
return tagNamePrefix + ":" + tagName;
}
public void setTagNamePrefix(String tagNamePrefix) {
this.tagNamePrefix = tagNamePrefix;
}
public String getBpmnJsCreationCode() {
return bpmnJsCreationCode.toString();
}
public void clearBPMN() {
bpmnComponents.clear();
bpmnSeqFlowComponents.clear();
nsTagNamePrefixes.clear();
}
public void loadBPMN(String fileURL) {
clearBPMN();
if (fileURL == null) {
log.debug("fileURL was null");
return;
}
// read from url
InputStream in = null;
try {
URL url = new URL(fileURL);
in = url.openStream();
} catch (MalformedURLException e1) {
log.error(e1.getLocalizedMessage());
return;
} catch (IOException e2) {
log.error(e2.getLocalizedMessage());
return;
}
readXML(in);
try {
in.close();
} catch (IOException e) {
log.error(e.getLocalizedMessage());
}
}
public void readXML(InputStream inputStream) {
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputStream);
// optional, but recommended
// read this -
// http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
doc.getDocumentElement().normalize();
log.debug("Root element :"
+ doc.getDocumentElement().getNodeName());
fillNsTagNamePrefixes(doc);
log.debug("----------------------------");
NodeList nBpmnProcessList = getElementsByTagNameIntern(doc, BPMN_PROCESS);
log.debug("----------------------------");
readBpmnProcessNodeList(doc, nBpmnProcessList);
if (bpmnComponents.isEmpty()){
readDiagramNodes(doc);
}
printOutBpmnComponents();
fillCreatedBpmnComponentJsStatements();
fillCreatedSeqFlowBpmnComponentJsStatements();
} catch (Exception e) {
log.error("{}", e);
}
}
private void fillNsTagNamePrefixes(Document doc){
NamedNodeMap namedNodeMap = doc.getDocumentElement().getAttributes();
for (int i = 0; i < namedNodeMap.getLength(); i++) {
Node nNode = namedNodeMap.item(i);
String nNodeName = nNode.getNodeName();
if (nNodeName != null && nNodeName.startsWith(XMLNS_PREFIX)){
log.debug("namedNode: {}", nNodeName);
String prefix = nNodeName.substring(XMLNS_PREFIX.length(), nNodeName.length());
log.debug("nsPrefix: {}", prefix);
nsTagNamePrefixes.add(nNodeName.substring(XMLNS_PREFIX.length(), nNodeName.length()));
}
}
}
private NodeList getElementsByTagNameIntern(Document doc, String tagName){
for (String nsTagNamePrefix : nsTagNamePrefixes) {
NodeList nodeList = doc.getElementsByTagName(nsTagNamePrefix + ":" + tagName);
if (nodeList.getLength() > 0){
setTagNamePrefix(nsTagNamePrefix);
return nodeList;
}
}
return emptyNodeList;
}
private void printOutBpmnComponents() {
log.debug("*************** BpmnComponent-Map *******************");
for (BpmnNode bpmnComponent : bpmnComponents.values()) {
String shape = (bpmnComponent.getShape() != null ? bpmnComponent.getShape().name() : "");
log.debug("\nID: " + bpmnComponent.getId());
log.debug("\nName: " + bpmnComponent.getName());
log.debug("\nX: " + bpmnComponent.getX());
log.debug("\nY: " + bpmnComponent.getY());
log.debug("\nWidth: " + bpmnComponent.getWidth());
log.debug("\nHeight: " + bpmnComponent.getHeight());
log.debug("\nTarget: " + bpmnComponent.getTarget());
log.debug("\nShape: {}", shape);
log.debug("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
log.debug("*****************************************************");
}
private void fillCreatedBpmnComponentJsStatements() {
bpmnJsCreationCode.setLength(0);
log.debug("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CreateBpmnComponentJsStatements ~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
String out;
for (BpmnNode bpmnComponent : bpmnComponents.values()) {
BpmnShape bpmnShape = bpmnComponent.getShape();
if (bpmnShape != null) {
switch (bpmnShape) {
case STARTEVENT:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateStart");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case MESSAGE_STARTEVENT:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateMessageStart");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case ENDEVENT:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateEnd");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case ERROR_ENDEVENT:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateErrorEnd");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case TASK:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateTask");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case USERTASK:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateUserTask");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case SCRIPTTASK:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateScriptTask");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case SERVICETASK:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateServiceTask");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case RECEIVETASK:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateReceiveTask");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case SENDTASK:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateSendTask");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case PARALLEL_GATEWAY:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateParallelCondition");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case EXCLUSIVE_GATEWAY:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateExclusiveCondition");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case INCLUSIVE_GATEWAY:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateInclusiveCondition");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
case CALL_ACTIVITY:
out = getCreateJsVarAsString(bpmnComponent, "bpmnCreateCallActivity");
bpmnJsCreationCode.append(out);
log.debug(out);
break;
default:
log.error("Shape not found {}", bpmnShape.name());
break;
}
}
}
log.debug("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
private void fillCreatedSeqFlowBpmnComponentJsStatements() {
log.debug("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CreateSeqFlowBpmnComponentJsStatements ~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
String out;
for (BpmnNode bpmnComponent : bpmnSeqFlowComponents.values()) {
BpmnShape bpmnShape = bpmnComponent.getShape();
if (bpmnShape != null && bpmnShape == BpmnShape.SEQ_FLOW) {
out = "\ninsertEdge(graph, parent, '" + bpmnComponent.getId() + "', '" + bpmnComponent.getName() + "', "
+ bpmnComponent.getSource().toLowerCase().replace("-", "_") + ", "
+ bpmnComponent.getTarget().toLowerCase().replace("-", "_") + ");";
bpmnJsCreationCode.append(out);
log.debug(out);
}
}
log.debug("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
private String getCreateJsVarAsString(BpmnNode bpmnComponent, String methodName) {
return "\nvar "
+ bpmnComponent.getId().toLowerCase().replace("-", "_")
+ " = " + methodName + "(graph, parent, '"
+ bpmnComponent.getId() + "', '"
+ bpmnComponent.getName() + "', "
+ bpmnComponent.getX() + ", "
+ bpmnComponent.getY() + ", "
+ bpmnComponent.getWidth() + ", "
+ bpmnComponent.getHeight() + ");";
}
private void readBpmnDiagramNodeList(NodeList nList) {
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
String nNodeName = nNode.getNodeName();
if (!"bpmndi:BPMNEdge".equals(nNodeName)) {
log.debug("\n===============================");
log.debug("\nCurrent Element :" + nNodeName);
log.debug("\n===============================");
Element eElement = (Element) nNode;
if ("dc:Bounds".equals(nNodeName)) {
Element parentElement = (Element) eElement
.getParentNode();
String bpmnElementKey = parentElement
.getAttribute("bpmnElement");
if (!bpmnElementKey.isEmpty()
&& bpmnComponents.containsKey(bpmnElementKey)) {
BpmnNode bpmnComponent = bpmnComponents
.get(bpmnElementKey);
log.debug(nNodeName + " bpmnElement : "
+ bpmnElementKey);
bpmnComponent.setX(new Float(eElement
.getAttribute("x")).intValue());
bpmnComponent.setY(new Float(eElement
.getAttribute("y")).intValue());
bpmnComponent.setWidth(new Float(eElement
.getAttribute("width")).intValue());
bpmnComponent.setHeight(new Float(eElement
.getAttribute("height")).intValue());
log.debug(nNodeName + " x : "
+ bpmnComponent.getX());
log.debug(nNodeName + " y : "
+ bpmnComponent.getY());
log.debug(nNodeName + " width : "
+ bpmnComponent.getWidth());
log.debug(nNodeName + " height : "
+ bpmnComponent.getHeight());
}
} else {
log.debug(nNodeName + " id : "
+ eElement.getAttribute("id"));
}
readBpmnDiagramNodeList(eElement.getChildNodes());
}
}
}
}
private void readBpmnProcessNodeList(Document doc, NodeList nList) {
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
String nNodeName = nNode.getNodeName();
log.debug("\nProcess: " + nNodeName);
log.debug("\n####################################");
if (getTagName(BPMN_PROCESS).equals(nNodeName)) {
Element eElement = (Element) nNode;
readBpmnProcessNodeList(doc, eElement.getChildNodes());
readDiagramNodes(doc);
} else {
if (getTagName(BPMN_START_EVENT).equals(nNodeName)) {
if (((Element) nNode).getElementsByTagName(getTagName(BPMN_MESSAGE_START_EVENT_DEF)).getLength()>0){
createMessageStartEvent(nNode);
} else {
createStartEvent(nNode);
}
} else if ((getTagName(BPMN_TASK).equals(nNodeName))) {
createTask(nNode);
} else if ((getTagName(BPMN_USER_TASK).equals(nNodeName))) {
createUserTask(nNode);
} else if ((getTagName(BPMN_SCRIPT_TASK).equals(nNodeName))) {
createScriptTask(nNode);
} else if ((getTagName(BPMN_SERVICE_TASK).equals(nNodeName))) {
createServiceTask(nNode);
} else if ((getTagName(BPMN_RECEIVE_TASK).equals(nNodeName))) {
createReceiveTask(nNode);
} else if ((getTagName(BPMN_SEND_TASK).equals(nNodeName))) {
createSendTask(nNode);
} else if ((getTagName(BPMN_PARALLEL_GATEWAY).equals(nNodeName))) {
createParallelGateway(nNode);
} else if ((getTagName(BPMN_EXCLUSIVE_GATEWAY).equals(nNodeName))) {
createExclusiveGateway(nNode);
} else if ((getTagName(BPMN_INCLUSIVE_GATEWAY).equals(nNodeName))) {
createInclusiveGateway(nNode);
} else if ((getTagName(BPMN_CALL_ACTIVITY).equals(nNodeName))) {
createCallActivity(nNode);
} else if ((getTagName(BPMN_END_EVENT).equals(nNodeName))) {
if (((Element) nNode).getElementsByTagName(getTagName(BPMN_ERROR_END_EVENT_DEF)).getLength()>0){
createErrorEndEvent(nNode);
} else {
createEndEvent(nNode);
}
} else if ((getTagName(BPMN_SEQ_FLOW).equals(nNodeName))) {
createSeqFlow(nNode);
}
}
}
}
}
private void readDiagramNodes(Document doc) {
NodeList nBpmnDiagramList = doc
.getElementsByTagName(BPMN_DIAGRAM);
readBpmnDiagramNodeList(nBpmnDiagramList);
}
private BpmnNode getBpmnComponent(Node nNode) {
String nNodeName = nNode.getNodeName();
log.debug("\n===============================");
log.debug("\nCurrent Element :" + nNodeName);
log.debug("\n===============================");
Element eElement = (Element) nNode;
String id = eElement.getAttribute("id");
BpmnNode bpmnComponent;
if (bpmnComponents.containsKey(id)) {
bpmnComponent = bpmnComponents.get(id);
} else {
bpmnComponent = new BpmnNode();
bpmnComponent.setId(id);
}
if (getTagName(BPMN_SEQ_FLOW).equals(nNodeName)) {
bpmnComponent.setSource(eElement.getAttribute("sourceRef"));
bpmnComponent.setTarget(eElement.getAttribute("targetRef"));
}
bpmnComponent.setName(eElement.getAttribute("name"));
log.debug(nNodeName + " id : " + bpmnComponent.getId());
log.debug(nNodeName + " name : " + bpmnComponent.getName());
return bpmnComponent;
}
private void createTask(Node nNode) {
BpmnNode task = getBpmnComponent(nNode);
task.setShape(BpmnShape.TASK);
bpmnComponents.put(task.getId(), task);
}
private void createUserTask(Node nNode) {
BpmnNode userTask = getBpmnComponent(nNode);
userTask.setShape(BpmnShape.USERTASK);
bpmnComponents.put(userTask.getId(), userTask);
}
private void createScriptTask(Node nNode) {
BpmnNode userTask = getBpmnComponent(nNode);
userTask.setShape(BpmnShape.SCRIPTTASK);
bpmnComponents.put(userTask.getId(), userTask);
}
private void createServiceTask(Node nNode) {
BpmnNode serviceTask = getBpmnComponent(nNode);
serviceTask.setShape(BpmnShape.SERVICETASK);
bpmnComponents.put(serviceTask.getId(), serviceTask);
}
private void createReceiveTask(Node nNode) {
BpmnNode userTask = getBpmnComponent(nNode);
userTask.setShape(BpmnShape.RECEIVETASK);
bpmnComponents.put(userTask.getId(), userTask);
}
private void createSendTask(Node nNode) {
BpmnNode userTask = getBpmnComponent(nNode);
userTask.setShape(BpmnShape.SENDTASK);
bpmnComponents.put(userTask.getId(), userTask);
}
private void createStartEvent(Node nNode) {
BpmnNode startEvent = getBpmnComponent(nNode);
startEvent.setShape(BpmnShape.STARTEVENT);
bpmnComponents.put(startEvent.getId(), startEvent);
}
private void createMessageStartEvent(Node nNode) {
BpmnNode startEvent = getBpmnComponent(nNode);
startEvent.setShape(BpmnShape.MESSAGE_STARTEVENT);
bpmnComponents.put(startEvent.getId(), startEvent);
}
private void createErrorEndEvent(Node nNode) {
BpmnNode endEvent = getBpmnComponent(nNode);
endEvent.setShape(BpmnShape.ERROR_ENDEVENT);
bpmnComponents.put(endEvent.getId(), endEvent);
}
private void createEndEvent(Node nNode) {
BpmnNode endEvent = getBpmnComponent(nNode);
endEvent.setShape(BpmnShape.ENDEVENT);
bpmnComponents.put(endEvent.getId(), endEvent);
}
private void createParallelGateway(Node nNode) {
BpmnNode createParallelGateway = getBpmnComponent(nNode);
createParallelGateway.setShape(BpmnShape.PARALLEL_GATEWAY);
bpmnComponents.put(createParallelGateway.getId(), createParallelGateway);
}
private void createExclusiveGateway(Node nNode) {
BpmnNode createExclusiveGateway = getBpmnComponent(nNode);
createExclusiveGateway.setShape(BpmnShape.EXCLUSIVE_GATEWAY);
bpmnComponents.put(createExclusiveGateway.getId(), createExclusiveGateway);
}
private void createInclusiveGateway(Node nNode) {
BpmnNode createExclusiveGateway = getBpmnComponent(nNode);
createExclusiveGateway.setShape(BpmnShape.INCLUSIVE_GATEWAY);
bpmnComponents.put(createExclusiveGateway.getId(), createExclusiveGateway);
}
private void createCallActivity(Node nNode) {
BpmnNode createCallActivity = getBpmnComponent(nNode);
createCallActivity.setShape(BpmnShape.CALL_ACTIVITY);
bpmnComponents.put(createCallActivity.getId(), createCallActivity);
}
private void createSeqFlow(Node nNode) {
BpmnNode createSeqFlow = getBpmnComponent(nNode);
createSeqFlow.setShape(BpmnShape.SEQ_FLOW);
bpmnSeqFlowComponents.put(createSeqFlow.getId(), createSeqFlow);
}
}