| /** |
| * |
| * 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 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * 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); |
| } |
| |
| } |