diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java index c58e0783..5f5f4023 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java @@ -124,6 +124,14 @@ public BPMNModel(Document doc) throws BPMNModelException { definitions = doc.getDocumentElement(); + // test if we have a default namespace without use of the 'bpmn:' prefix + // e.g: xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" + String defaultNameSpace = definitions.getAttribute("xmlns"); + if (defaultNameSpace != null && !defaultNameSpace.isEmpty()) { + setPrefix(BPMNNS.BPMN2, ""); + setUri(BPMNNS.BPMN2, defaultNameSpace); + } + // parse the BPMN namespaces NamedNodeMap defAttributes = definitions.getAttributes(); for (int j = 0; j < defAttributes.getLength(); j++) { @@ -168,36 +176,74 @@ public BPMNModel(Document doc) throws BPMNModelException { } } - // find bpmndi:BPMNDiagram - NodeList diagramList = doc.getElementsByTagName(getPrefix(BPMNNS.BPMNDI) + ":BPMNDiagram"); - if (diagramList != null && diagramList.getLength() > 0) { - bpmnDiagram = diagramList.item(0); - } else { - // no diagram included - so we create an empty one - getLogger().warning("No bpmndi:BPMNDiagram found - created default diagram"); - // - Element bpmnDiagram = createElement(BPMNNS.BPMNDI, "BPMNDiagram"); - bpmnDiagram.setAttribute("id", "BPMNDiagram_1"); - bpmnDiagram.setAttribute("name", "OpenBPMN Diagram"); - definitions.appendChild(bpmnDiagram); - setBpmnDiagram(bpmnDiagram); - } + // Load BPMNDiagram element.... + loadBpmnDiagram(); - // find BPMNPlane - NodeList planeList = doc.getElementsByTagName(getPrefix(BPMNNS.BPMNDI) + ":BPMNPlane"); - if (planeList != null && planeList.getLength() > 0) { - bpmnPlane = (Element) planeList.item(0); - } + // Load BPMNPlane element.... + loadBpmnPlane(); // init the participant and process list loadParticipantList(); loadProcessList(); + // load global elements loadMessageList(); loadMessageFlowList(); loadSignalList(); } } + /** + * This method loads the first BPMNDiagram element. If + * no BPMNDiagram yet exists, then the method build one. + * + */ + private void loadBpmnDiagram() { + // find bpmndi:BPMNDiagram + NodeList diagramList = doc.getElementsByTagName(getPrefix(BPMNNS.BPMNDI) + "BPMNDiagram"); + if (diagramList != null && diagramList.getLength() > 0) { + bpmnDiagram = diagramList.item(0); + } else { + // no diagram included - so we create an empty one + getLogger().warning("No bpmndi:BPMNDiagram found - created default diagram"); + // + Element bpmnDiagram = createElement(BPMNNS.BPMNDI, "BPMNDiagram"); + bpmnDiagram.setAttribute("id", "BPMNDiagram_1"); + bpmnDiagram.setAttribute("name", "OpenBPMN Diagram"); + definitions.appendChild(bpmnDiagram); + setBpmnDiagram(bpmnDiagram); + } + } + + /** + * This method loads the first BPMNPlane from the BPMNDiagram. If + * no BPMN Plane yet exists, then the method build one. + * + */ + private void loadBpmnPlane() { + // find the corresponding BPMNPlane + NodeList planeList = doc.getElementsByTagName(getPrefix(BPMNNS.BPMNDI) + "BPMNPlane"); + if (planeList != null && planeList.getLength() > 0) { + bpmnPlane = (Element) planeList.item(0); + } + // if no plane exists yes, we create one + if (bpmnPlane == null) { + // + getLogger().warning("No bpmndi:BPMNPlane found - created default plane"); + bpmnPlane = createElement(BPMNNS.BPMNDI, "BPMNPlane"); + bpmnPlane.setAttribute("id", "BPMNPlane_1"); + NodeList nodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "collaboration"); + if (nodeList == null || nodeList.getLength() == 0) { + // Take the default process as plane ref... + nodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "process"); + } + if (nodeList != null && nodeList.getLength() > 0) { + Element refElement = (Element) nodeList.item(0); + bpmnPlane.setAttribute("bpmnElement", refElement.getAttribute("id")); + } + getBpmnDiagram().appendChild(bpmnPlane); + } + } + /** * Returns the namespace uri for a given namespace * @@ -230,9 +276,20 @@ public String getPrefix(BPMNNS ns) { /** * Updates the namespace prefix for a given BPMN namespace - e.g. 'bpmn2' or * 'bpmndi' + * The method automatically adds the prefix separator ':' if the prefix is not + * empty. This is necessary to handle default namespaces without a prefix + * correctly */ public void setPrefix(BPMNNS ns, String prefix) { - PREFIX_BY_NAMESPACE.put(ns, prefix); + if (prefix == null) { + prefix = ""; + } + if (prefix.isEmpty()) { + PREFIX_BY_NAMESPACE.put(ns, prefix); + } else { + PREFIX_BY_NAMESPACE.put(ns, prefix + ":"); + } + } public Element getDefinitions() { @@ -664,7 +721,7 @@ public void deleteParticipant(Participant participant) { * Creates an element with a given namespace */ public Element createElement(BPMNNS ns, String type) { - Element element = this.getDoc().createElementNS(getUri(ns), getPrefix(ns) + ":" + type); + Element element = this.getDoc().createElementNS(getUri(ns), getPrefix(ns) + type); return element; } @@ -747,8 +804,8 @@ public void deleteMessageFlow(String id) { for (int j = 0; j < childs.getLength(); j++) { Node child = childs.item(j); if (child.getNodeType() == Node.ELEMENT_NODE - && (child.getNodeName().equals(getPrefix(BPMNNS.BPMN2) + ":incoming") - || child.getNodeName().equals(getPrefix(BPMNNS.BPMN2) + ":outgoing"))) { + && (child.getNodeName().equals(getPrefix(BPMNNS.BPMN2) + "incoming") + || child.getNodeName().equals(getPrefix(BPMNNS.BPMN2) + "outgoing"))) { if (id.equals(child.getTextContent())) { targetElement.getElementNode().removeChild(child); break; @@ -762,8 +819,8 @@ public void deleteMessageFlow(String id) { for (int j = 0; j < childs.getLength(); j++) { Node child = childs.item(j); if (child.getNodeType() == Node.ELEMENT_NODE - && (child.getNodeName().equals(getPrefix(BPMNNS.BPMN2) + ":incoming") - || child.getNodeName().equals(getPrefix(BPMNNS.BPMN2) + ":outgoing"))) { + && (child.getNodeName().equals(getPrefix(BPMNNS.BPMN2) + "incoming") + || child.getNodeName().equals(getPrefix(BPMNNS.BPMN2) + "outgoing"))) { if (id.equals(child.getTextContent())) { sourceElement.getElementNode().removeChild(child); break; @@ -1342,7 +1399,7 @@ public Participant findParticipantByProcessId(String processId) { public Set findChildNodesByName(Element parent, BPMNNS ns, String nodeName) { Set result = new LinkedHashSet(); // resolve the tag name - String tagName = getPrefix(ns) + ":" + nodeName; + String tagName = getPrefix(ns) + nodeName; if (parent != null && nodeName != null) { NodeList childs = parent.getChildNodes(); for (int i = 0; i < childs.getLength(); i++) { @@ -1650,7 +1707,7 @@ public Node findBPMNPlaneElement(String nodeName, String id) { if (id == null || id.isEmpty() || bpmnPlane == null || nodeName == null) { return null; } - String fullNodeName = getPrefix(BPMNNS.BPMNDI) + ":" + nodeName; + String fullNodeName = getPrefix(BPMNNS.BPMNDI) + nodeName; NodeList childList = bpmnPlane.getChildNodes(); for (int i = 0; i < childList.getLength(); i++) { Node child = childList.item(i); @@ -1710,14 +1767,14 @@ public static void debug(String message) { private void loadParticipantList() throws BPMNModelException { participants = new LinkedHashSet(); List invalidParticipantElementList = new ArrayList(); - NodeList collaborationNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + ":collaboration"); + NodeList collaborationNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "collaboration"); if (collaborationNodeList != null && collaborationNodeList.getLength() > 0) { // we only take the first collaboration element (this is what is expected) collaborationElement = (Element) collaborationNodeList.item(0); // now find all participants... NodeList participantList = collaborationElement - .getElementsByTagName(getPrefix(BPMNNS.BPMN2) + ":participant"); + .getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "participant"); logger.fine("..found " + participantList.getLength() + " participants"); for (int i = 0; i < participantList.getLength(); i++) { Element item = (Element) participantList.item(i); @@ -1761,7 +1818,7 @@ private void loadProcessList() throws BPMNModelException { int publicCount = 0; // find process - NodeList processList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + ":process"); + NodeList processList = definitions.getElementsByTagNameNS(getUri(BPMNNS.BPMN2), "process"); if (processList != null && processList.getLength() > 0) { for (int i = 0; i < processList.getLength(); i++) { Element item = (Element) processList.item(i); @@ -1851,13 +1908,13 @@ private void loadProcessList() throws BPMNModelException { */ private void loadMessageFlowList() throws BPMNModelException { messageFlows = new LinkedHashSet(); - NodeList collaborationNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + ":collaboration"); + NodeList collaborationNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "collaboration"); if (collaborationNodeList != null && collaborationNodeList.getLength() > 0) { // we only take the first collaboration element (this is what is expected) collaborationElement = (Element) collaborationNodeList.item(0); // now find all messageFlows... NodeList messageFlowList = collaborationElement - .getElementsByTagName(getPrefix(BPMNNS.BPMN2) + ":" + BPMNTypes.MESSAGE_FLOW); + .getElementsByTagName(getPrefix(BPMNNS.BPMN2) + BPMNTypes.MESSAGE_FLOW); logger.fine("..found " + messageFlowList.getLength() + " messageFlows"); for (int i = 0; i < messageFlowList.getLength(); i++) { Element item = (Element) messageFlowList.item(i); @@ -1878,7 +1935,7 @@ private void loadMessageFlowList() throws BPMNModelException { private void loadSignalList() throws BPMNModelException { signals = new LinkedHashSet(); List duplicates = new ArrayList<>(); - NodeList signalNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + ":" + BPMNTypes.SIGNAL); + NodeList signalNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + BPMNTypes.SIGNAL); if (signalNodeList != null && signalNodeList.getLength() > 0) { for (int i = 0; i < signalNodeList.getLength(); i++) { Element item = (Element) signalNodeList.item(i); @@ -1902,7 +1959,7 @@ private void loadSignalList() throws BPMNModelException { */ private void loadMessageList() throws BPMNModelException { messages = new LinkedHashSet(); - NodeList messageNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + ":" + BPMNTypes.MESSAGE); + NodeList messageNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + BPMNTypes.MESSAGE); if (messageNodeList != null && messageNodeList.getLength() > 0) { for (int i = 0; i < messageNodeList.getLength(); i++) { Element item = (Element) messageNodeList.item(i); diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/BPMNProcess.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/BPMNProcess.java index a2620792..3c3373d4 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/BPMNProcess.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/BPMNProcess.java @@ -930,8 +930,8 @@ private void removeElementEdge(String id) { for (int j = 0; j < childs.getLength(); j++) { Node child = childs.item(j); if (child.getNodeType() == Node.ELEMENT_NODE - && (child.getNodeName().equals(getModel().getPrefix(BPMNNS.BPMN2) + ":incoming") - || child.getNodeName().equals(getModel().getPrefix(BPMNNS.BPMN2) + ":outgoing"))) { + && (child.getNodeName().equals(getModel().getPrefix(BPMNNS.BPMN2) + "incoming") + || child.getNodeName().equals(getModel().getPrefix(BPMNNS.BPMN2) + "outgoing"))) { if (id.equals(child.getTextContent())) { targetElement.getElementNode().removeChild(child); break; @@ -946,8 +946,8 @@ private void removeElementEdge(String id) { for (int j = 0; j < childs.getLength(); j++) { Node child = childs.item(j); if (child.getNodeType() == Node.ELEMENT_NODE - && (child.getNodeName().equals(getModel().getPrefix(BPMNNS.BPMN2) + ":incoming") - || child.getNodeName().equals(getModel().getPrefix(BPMNNS.BPMN2) + ":outgoing"))) { + && (child.getNodeName().equals(getModel().getPrefix(BPMNNS.BPMN2) + "incoming") + || child.getNodeName().equals(getModel().getPrefix(BPMNNS.BPMN2) + "outgoing"))) { if (id.equals(child.getTextContent())) { sourceElement.getElementNode().removeChild(child); break; diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNBounds.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNBounds.java index 333db6c7..44155ec9 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNBounds.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNBounds.java @@ -44,7 +44,7 @@ public BPMNBounds(Node _bpmndiElement, BPMNModel model) throws BPMNMissingElemen NodeList childList = bpmndiElement.getChildNodes(); for (int i = 0; i < childList.getLength(); i++) { Node child = childList.item(i); - if ((model.getPrefix(BPMNNS.DC) + ":Bounds").equals(child.getNodeName()) && child.hasAttributes()) { + if ((model.getPrefix(BPMNNS.DC) + "Bounds").equals(child.getNodeName()) && child.hasAttributes()) { elementNode = (Element) child; break; } diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementEdge.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementEdge.java index 57b69d48..01f1e49a 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementEdge.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementEdge.java @@ -290,7 +290,7 @@ public void clearWayPoints() { // find all di:waypoint for (int i = 0; i < childList.getLength(); i++) { Node child = childList.item(i); - if ((model.getPrefix(BPMNNS.DI) + ":waypoint").equals(child.getNodeName()) && child.hasAttributes()) { + if ((model.getPrefix(BPMNNS.DI) + "waypoint").equals(child.getNodeName()) && child.hasAttributes()) { // collect node.... deletionList.add(child); } diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementNode.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementNode.java index d83f88d1..938f7c93 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementNode.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementNode.java @@ -317,7 +317,7 @@ public void updateSequenceFlowReferences() { } // remove incoming childs... NodeList incomingSequenceFlows = getElementNode() - .getElementsByTagName(bpmnProcess.getModel().getPrefix(BPMNNS.BPMN2) + ":incoming"); + .getElementsByTagName(bpmnProcess.getModel().getPrefix(BPMNNS.BPMN2) + "incoming"); for (int i = 0; i < incomingSequenceFlows.getLength(); i++) { Element item = (Element) incomingSequenceFlows.item(i); // test if the sequence flow exists... @@ -332,7 +332,7 @@ public void updateSequenceFlowReferences() { } // remove outgoing childs... NodeList outgoingSequenceFlows = getElementNode() - .getElementsByTagName(bpmnProcess.getModel().getPrefix(BPMNNS.BPMN2) + ":outgoing"); + .getElementsByTagName(bpmnProcess.getModel().getPrefix(BPMNNS.BPMN2) + "outgoing"); for (int i = 0; i < outgoingSequenceFlows.getLength(); i++) { Element item = (Element) outgoingSequenceFlows.item(i); // test if the sequence flow exists... diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNLabel.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNLabel.java index 0f69f4e7..6a35cbca 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNLabel.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNLabel.java @@ -47,7 +47,7 @@ public BPMNLabel(BPMNModel model, Node _bpmnShape) throws BPMNMissingElementExce NodeList childList = bpmnShape.getChildNodes(); for (int i = 0; i < childList.getLength(); i++) { Node child = childList.item(i); - if ((model.getPrefix(BPMNNS.BPMNDI) + ":BPMNLabel").equals(child.getNodeName())) { + if ((model.getPrefix(BPMNNS.BPMNDI) + "BPMNLabel").equals(child.getNodeName())) { label = (Element) child; // find the dc:Bounds element of the label... diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/util/BPMNModelFactory.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/util/BPMNModelFactory.java index ea778726..d86f3834 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/util/BPMNModelFactory.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/util/BPMNModelFactory.java @@ -165,19 +165,10 @@ public static BPMNModel read(InputStream is, Path path) throws BPMNModelExceptio // explicit remove whitespace removeWhitespaceNodes(root); + BPMNModel model = new BPMNModel(doc); + setOpenBPMNNameSpace(model.getDefinitions()); - if (!"bpmn2:definitions".equals(root.getNodeName()) - && - !"bpmn:definitions".equals(root.getNodeName())) { - logger.severe("Invalid BPMN File: Missing root element 'bpmn2:definitions'!"); - return null; - } else { - BPMNModel model = new BPMNModel(doc); - setOpenBPMNNameSpace(model.getDefinitions()); - - return model; - } - + return model; } catch (ParserConfigurationException | SAXException | IOException e) { logger.severe(e.getMessage()); // create a runtimeException to show a error message in the client diff --git a/open-bpmn.metamodel/src/test/java/org/openbpmn/dom/TestReadDom.java b/open-bpmn.metamodel/src/test/java/org/openbpmn/dom/TestReadDom.java index 2be2a58c..b42e409f 100644 --- a/open-bpmn.metamodel/src/test/java/org/openbpmn/dom/TestReadDom.java +++ b/open-bpmn.metamodel/src/test/java/org/openbpmn/dom/TestReadDom.java @@ -106,7 +106,28 @@ public void testReadEmptyModelWithCustomNamespace() throws BPMNModelException { // next validate the BPMN Default Namespaces assertEquals("http://www.omg.org/spec/BPMN/20100524/MODEL", model.getUri(BPMNNS.BPMN2)); - logger.info("...model read sucessful"); + logger.info("...model read successful"); + + } + + /** + * This Test verifies if a BPMN model with custom namespace URIs can be read if + * no bpmn2: exists + * + * @throws BPMNModelException + * + */ + @Test + public void testReadModelWithoutBPMN2Prefix() throws BPMNModelException { + + logger.info("...read model"); + + BPMNModel model = BPMNModelFactory.read("/process_1_custom_namespace-nopaefix.bpmn"); + System.out.println("Root Element :" + model.getDoc().getDocumentElement().getNodeName()); + // next validate the default namespace mapped to bpmn2 + assertEquals("http://www.omg.org/spec/BPMN/20100524/MODEL", model.getUri(BPMNNS.BPMN2)); + + logger.info("...model read successful"); } diff --git a/open-bpmn.metamodel/src/test/resources/process_1_custom_namespace-nopaefix.bpmn b/open-bpmn.metamodel/src/test/resources/process_1_custom_namespace-nopaefix.bpmn new file mode 100644 index 00000000..97dde214 --- /dev/null +++ b/open-bpmn.metamodel/src/test/resources/process_1_custom_namespace-nopaefix.bpmn @@ -0,0 +1,96 @@ + + + + + + + G94506efc9c90484c94f76ab9d865c3f3 + + + + G94506efc9c90484c94f76ab9d865c3f3 + + G3c32d4362fb34202afdd71d832bea159 + + + + + + G3c32d4362fb34202afdd71d832bea159 + + G1368eaa247794e79aba99e78faa68b43 + + G690fc96a505e46ac8e1bb836e91a68f7 + + + + + G1368eaa247794e79aba99e78faa68b43 + + G6f4b004c57ff4fd69a2e8d47969a1cd4 + + + + + G690fc96a505e46ac8e1bb836e91a68f7 + + Gd008894c897342c7a2df989d8512e647 + + + + + + G6f4b004c57ff4fd69a2e8d47969a1cd4 + + Gd008894c897342c7a2df989d8512e647 + + Gf65d4f6da8fe49d8bbeca90cfc23f130 + + + + Gf65d4f6da8fe49d8bbeca90cfc23f130 + + Ge5fdf5a3ace64afeb0391770454d319a + + G0156d62645cd41979c4f60dacadaf76e + + + + + + Name muss Klaus seinx + => x.Name == "Klaus" + + + + Ge5fdf5a3ace64afeb0391770454d319a + + Gfd21215af7fb4334962afd070b3dafd7 + + + + + G0156d62645cd41979c4f60dacadaf76e + + Gfd21215af7fb4334962afd070b3dafd7 + + + + + + + \ No newline at end of file