Skip to content

Commit 2d3a17b

Browse files
committed
rebuild parsing of namespaces (Issue #402)
1 parent 001e919 commit 2d3a17b

4 files changed

Lines changed: 159 additions & 85 deletions

File tree

open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java

Lines changed: 125 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -124,57 +124,8 @@ public BPMNModel(Document doc) throws BPMNModelException {
124124

125125
definitions = doc.getDocumentElement();
126126

127-
// test if we have a default namespace without use of the 'bpmn:' prefix
128-
// e.g: xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
129-
String defaultNameSpace = definitions.getAttribute("xmlns");
130-
if (defaultNameSpace != null && !defaultNameSpace.isEmpty()) {
131-
setPrefix(BPMNNS.BPMN2, "");
132-
setUri(BPMNNS.BPMN2, defaultNameSpace);
133-
}
134-
135-
// parse the BPMN namespaces
136-
NamedNodeMap defAttributes = definitions.getAttributes();
137-
for (int j = 0; j < defAttributes.getLength(); j++) {
138-
Node node = defAttributes.item(j);
139-
// update to new namespace uri if not matching the default URI
140-
// NOTE:
141-
// The primary namespace can be either 'bpmn2' or 'bpmn' !
142-
if ("bpmn".equals(node.getLocalName()) || "bpmn2".equals(node.getLocalName())) {
143-
144-
// In case the deprecated 'bpmn' namespace is used, we need to adjust the
145-
// internal prefix...
146-
if ("bpmn".equals(node.getLocalName())) {
147-
setPrefix(BPMNNS.BPMN2, "bpmn");
148-
}
149-
150-
if (!getUri(BPMNNS.BPMN2).equals(node.getNodeValue())) {
151-
logger.warning("...set BPMN namespace URI: " + node.getNodeValue());
152-
setUri(BPMNNS.BPMN2, node.getNodeValue());
153-
}
154-
}
155-
156-
if (getPrefix(BPMNNS.BPMN2).equals(node.getLocalName())
157-
&& !getUri(BPMNNS.BPMN2).equals(node.getNodeValue())) {
158-
logger.fine("...set BPMN2 namespace URI: " + node.getNodeValue());
159-
setUri(BPMNNS.BPMN2, node.getNodeValue());
160-
}
161-
162-
if (getPrefix(BPMNNS.BPMNDI).equals(node.getLocalName())
163-
&& !getUri(BPMNNS.BPMNDI).equals(node.getNodeValue())) {
164-
logger.fine("...set BPMNDI namespace URI: " + node.getNodeValue());
165-
setUri(BPMNNS.BPMNDI, node.getNodeValue());
166-
}
167-
if (getPrefix(BPMNNS.DC).equals(node.getLocalName())
168-
&& !getUri(BPMNNS.DC).equals(node.getNodeValue())) {
169-
logger.fine("...set DC namespace URI: " + node.getNodeValue());
170-
setUri(BPMNNS.DC, node.getNodeValue());
171-
}
172-
if (getPrefix(BPMNNS.DI).equals(node.getLocalName())
173-
&& !getUri(BPMNNS.DI).equals(node.getNodeValue())) {
174-
logger.fine("...set DI namespace URI: " + node.getNodeValue());
175-
setUri(BPMNNS.DI, node.getNodeValue());
176-
}
177-
}
127+
// Parse all namespaces using the new URI-based method
128+
parseAllNamespaces();
178129

179130
// Load BPMNDiagram element....
180131
loadBpmnDiagram();
@@ -192,25 +143,107 @@ public BPMNModel(Document doc) throws BPMNModelException {
192143

193144
}
194145

146+
/**
147+
* Helper method to parse all namespaces based on the uri
148+
*/
149+
private void parseAllNamespaces() {
150+
// Test for default namespace without prefix
151+
String defaultNameSpace = definitions.getAttribute("xmlns");
152+
if (defaultNameSpace != null && !defaultNameSpace.isEmpty()) {
153+
if (getUri(BPMNNS.BPMN2).equals(defaultNameSpace)) {
154+
setPrefix(BPMNNS.BPMN2, "");
155+
}
156+
}
157+
158+
// Parse all namespace attributes
159+
NamedNodeMap defAttributes = definitions.getAttributes();
160+
for (int j = 0; j < defAttributes.getLength(); j++) {
161+
Node node = defAttributes.item(j);
162+
String nodeName = node.getNodeName();
163+
String nodeValue = node.getNodeValue();
164+
165+
// Skip non-namespace attributes
166+
if (!nodeName.startsWith("xmlns:")) {
167+
continue;
168+
}
169+
170+
String prefix = node.getLocalName(); // Gets the part after 'xmlns:'
171+
172+
// Map URIs to their corresponding BPMN namespace types
173+
mapUriToNamespace(prefix, nodeValue);
174+
}
175+
}
176+
177+
/**
178+
* Helper method that maps a URI to the correct BPMN namespace based on the URI
179+
* value
180+
*/
181+
private void mapUriToNamespace(String prefix, String uri) {
182+
// BPMN2 Model namespace variants
183+
if ("http://www.omg.org/spec/BPMN/20100524/MODEL".equals(uri)) {
184+
setPrefix(BPMNNS.BPMN2, prefix);
185+
setUri(BPMNNS.BPMN2, uri);
186+
return;
187+
}
188+
189+
// BPMN DI namespace - can be mapped to different prefixes!
190+
if ("http://www.omg.org/spec/BPMN/20100524/DI".equals(uri)) {
191+
setPrefix(BPMNNS.BPMNDI, prefix);
192+
setUri(BPMNNS.BPMNDI, uri);
193+
return;
194+
}
195+
196+
// DC namespace
197+
if ("http://www.omg.org/spec/DD/20100524/DC".equals(uri)) {
198+
setPrefix(BPMNNS.DC, prefix);
199+
setUri(BPMNNS.DC, uri);
200+
return;
201+
}
202+
203+
// DI namespace
204+
if ("http://www.omg.org/spec/DD/20100524/DI".equals(uri)) {
205+
setPrefix(BPMNNS.DI, prefix);
206+
setUri(BPMNNS.DI, uri);
207+
return;
208+
}
209+
}
210+
211+
/*
212+
* Search a specific node by its namespace and element name
213+
*/
214+
public NodeList findElementsByName(Element parent, BPMNNS namespace, String elementName) {
215+
// 1. Versuch: Mit Prefix
216+
NodeList result = parent.getElementsByTagName(getPrefix(namespace) + elementName);
217+
if (result != null && result.getLength() > 0) {
218+
return result;
219+
}
220+
221+
// 2. Fallback: with URI if prefix is empty
222+
return parent.getElementsByTagNameNS(getUri(namespace), elementName);
223+
}
224+
195225
/**
196226
* This method loads the first BPMNDiagram element. If
197227
* no BPMNDiagram yet exists, then the method build one.
198228
*
199229
*/
200230
private void loadBpmnDiagram() {
201231
// find bpmndi:BPMNDiagram
202-
NodeList diagramList = doc.getElementsByTagName(getPrefix(BPMNNS.BPMNDI) + "BPMNDiagram");
232+
// NodeList diagramList = doc.getElementsByTagName(getPrefix(BPMNNS.BPMNDI) +
233+
// "BPMNDiagram");
234+
NodeList diagramList = findElementsByName(doc.getDocumentElement(), BPMNNS.BPMNDI, "BPMNDiagram");
203235
if (diagramList != null && diagramList.getLength() > 0) {
204236
bpmnDiagram = diagramList.item(0);
205237
} else {
238+
logger.warning("Fatal Diagram Error - no BPMNDiagram element found!");
206239
// no diagram included - so we create an empty one
207-
getLogger().warning("No bpmndi:BPMNDiagram found - created default diagram");
208-
// <bpmndi:BPMNDiagram id="BPMNDiagram_1" name="Default Process Diagram">
209-
Element bpmnDiagram = createElement(BPMNNS.BPMNDI, "BPMNDiagram");
210-
bpmnDiagram.setAttribute("id", "BPMNDiagram_1");
211-
bpmnDiagram.setAttribute("name", "OpenBPMN Diagram");
212-
definitions.appendChild(bpmnDiagram);
213-
setBpmnDiagram(bpmnDiagram);
240+
// getLogger().warning("No bpmndi:BPMNDiagram found - created default diagram");
241+
// // <bpmndi:BPMNDiagram id="BPMNDiagram_1" name="Default Process Diagram">
242+
// Element bpmnDiagram = createElement(BPMNNS.BPMNDI, "BPMNDiagram");
243+
// bpmnDiagram.setAttribute("id", "BPMNDiagram_1");
244+
// bpmnDiagram.setAttribute("name", "OpenBPMN Diagram");
245+
// definitions.appendChild(bpmnDiagram);
246+
// setBpmnDiagram(bpmnDiagram);
214247
}
215248
}
216249

@@ -221,7 +254,9 @@ private void loadBpmnDiagram() {
221254
*/
222255
private void loadBpmnPlane() {
223256
// find the corresponding BPMNPlane
224-
NodeList planeList = doc.getElementsByTagName(getPrefix(BPMNNS.BPMNDI) + "BPMNPlane");
257+
// NodeList planeList = doc.getElementsByTagName(getPrefix(BPMNNS.BPMNDI) +
258+
// "BPMNPlane");
259+
NodeList planeList = findElementsByName(doc.getDocumentElement(), BPMNNS.BPMNDI, "BPMNPlane");
225260
if (planeList != null && planeList.getLength() > 0) {
226261
bpmnPlane = (Element) planeList.item(0);
227262
}
@@ -231,10 +266,14 @@ private void loadBpmnPlane() {
231266
getLogger().warning("No bpmndi:BPMNPlane found - created default plane");
232267
bpmnPlane = createElement(BPMNNS.BPMNDI, "BPMNPlane");
233268
bpmnPlane.setAttribute("id", "BPMNPlane_1");
234-
NodeList nodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "collaboration");
269+
// NodeList nodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2)
270+
// + "collaboration");
271+
NodeList nodeList = findElementsByName(definitions, BPMNNS.BPMN2, "collaboration");
235272
if (nodeList == null || nodeList.getLength() == 0) {
236273
// Take the default process as plane ref...
237-
nodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "process");
274+
// nodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) +
275+
// "process");
276+
nodeList = findElementsByName(definitions, BPMNNS.BPMN2, "process");
238277
}
239278
if (nodeList != null && nodeList.getLength() > 0) {
240279
Element refElement = (Element) nodeList.item(0);
@@ -1873,14 +1912,19 @@ private void loadParticipantList() throws BPMNModelException {
18731912
int publicCount = 0;
18741913
participants = new LinkedHashSet<Participant>();
18751914
List<Element> invalidParticipantElementList = new ArrayList<Element>();
1876-
NodeList collaborationNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "collaboration");
1915+
// NodeList collaborationNodeList =
1916+
// definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "collaboration");
1917+
NodeList collaborationNodeList = findElementsByName(definitions, BPMNNS.BPMN2, "collaboration");
1918+
18771919
if (collaborationNodeList != null && collaborationNodeList.getLength() > 0) {
18781920

18791921
// we only take the first collaboration element (this is what is expected)
18801922
collaborationElement = (Element) collaborationNodeList.item(0);
18811923
// now find all participants...
1882-
NodeList participantList = collaborationElement
1883-
.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "participant");
1924+
// NodeList participantList = collaborationElement
1925+
// .getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "participant");
1926+
NodeList participantList = findElementsByName(collaborationElement, BPMNNS.BPMN2, "participant");
1927+
18841928
logger.fine("..found " + participantList.getLength() + " participants");
18851929
for (int i = 0; i < participantList.getLength(); i++) {
18861930
Element item = (Element) participantList.item(i);
@@ -1945,7 +1989,9 @@ private void loadProcessList() throws BPMNModelException {
19451989
int publicCount = 0;
19461990

19471991
// find process
1948-
NodeList processList = definitions.getElementsByTagNameNS(getUri(BPMNNS.BPMN2), "process");
1992+
// NodeList processList =
1993+
// definitions.getElementsByTagNameNS(getUri(BPMNNS.BPMN2), "process");
1994+
NodeList processList = findElementsByName(definitions, BPMNNS.BPMN2, "process");
19491995
if (processList != null && processList.getLength() > 0) {
19501996

19511997
// first we need to test if all processes have a processType attribute or if we
@@ -2005,13 +2051,16 @@ private void loadProcessList() throws BPMNModelException {
20052051
*/
20062052
private void loadMessageFlowList() throws BPMNModelException {
20072053
messageFlows = new LinkedHashSet<MessageFlow>();
2008-
NodeList collaborationNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "collaboration");
2054+
// NodeList collaborationNodeList =
2055+
// definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + "collaboration");
2056+
NodeList collaborationNodeList = findElementsByName(definitions, BPMNNS.BPMN2, "collaboration");
20092057
if (collaborationNodeList != null && collaborationNodeList.getLength() > 0) {
20102058
// we only take the first collaboration element (this is what is expected)
20112059
collaborationElement = (Element) collaborationNodeList.item(0);
20122060
// now find all messageFlows...
2013-
NodeList messageFlowList = collaborationElement
2014-
.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + BPMNTypes.MESSAGE_FLOW);
2061+
// NodeList messageFlowList = collaborationElement
2062+
// .getElementsByTagName(getPrefix(BPMNNS.BPMN2) + BPMNTypes.MESSAGE_FLOW);
2063+
NodeList messageFlowList = findElementsByName(collaborationElement, BPMNNS.BPMN2, BPMNTypes.MESSAGE_FLOW);
20152064
logger.fine("..found " + messageFlowList.getLength() + " messageFlows");
20162065
for (int i = 0; i < messageFlowList.getLength(); i++) {
20172066
Element item = (Element) messageFlowList.item(i);
@@ -2032,7 +2081,9 @@ private void loadMessageFlowList() throws BPMNModelException {
20322081
private void loadSignalList() throws BPMNModelException {
20332082
signals = new LinkedHashSet<Signal>();
20342083
List<String> duplicates = new ArrayList<>();
2035-
NodeList signalNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + BPMNTypes.SIGNAL);
2084+
// NodeList signalNodeList =
2085+
// definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + BPMNTypes.SIGNAL);
2086+
NodeList signalNodeList = findElementsByName(definitions, BPMNNS.BPMN2, BPMNTypes.SIGNAL);
20362087
if (signalNodeList != null && signalNodeList.getLength() > 0) {
20372088
for (int i = 0; i < signalNodeList.getLength(); i++) {
20382089
Element item = (Element) signalNodeList.item(i);
@@ -2056,7 +2107,10 @@ private void loadSignalList() throws BPMNModelException {
20562107
*/
20572108
private void loadMessageList() throws BPMNModelException {
20582109
messages = new LinkedHashSet<Message>();
2059-
NodeList messageNodeList = definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) + BPMNTypes.MESSAGE);
2110+
// NodeList messageNodeList =
2111+
// definitions.getElementsByTagName(getPrefix(BPMNNS.BPMN2) +
2112+
// BPMNTypes.MESSAGE);
2113+
NodeList messageNodeList = findElementsByName(definitions, BPMNNS.BPMN2, BPMNTypes.MESSAGE);
20602114
if (messageNodeList != null && messageNodeList.getLength() > 0) {
20612115
for (int i = 0; i < messageNodeList.getLength(); i++) {
20622116
Element item = (Element) messageNodeList.item(i);

open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/BPMNProcess.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,11 @@ public void init() throws BPMNModelException {
174174
private void autoFixUnassignedTextAnnotations() throws BPMNModelException {
175175
if (this.isPublicProcess() && this.model.isCollaborationDiagram()
176176
&& this.model.getCollaborationElement() != null) {
177-
NodeList textAnnotationNodeList = this.model.getCollaborationElement()
178-
.getElementsByTagName(this.model.getPrefix(BPMNNS.BPMN2) + BPMNTypes.TEXTANNOTATION);
177+
// NodeList textAnnotationNodeList = this.model.getCollaborationElement()
178+
// .getElementsByTagName(this.model.getPrefix(BPMNNS.BPMN2) +
179+
// BPMNTypes.TEXTANNOTATION);
180+
NodeList textAnnotationNodeList = this.model.findElementsByName(this.model.getCollaborationElement(),
181+
BPMNNS.BPMN2, BPMNTypes.TEXTANNOTATION);
179182
if (textAnnotationNodeList != null && textAnnotationNodeList.getLength() > 0) {
180183
for (int i = 0; i < textAnnotationNodeList.getLength(); i++) {
181184
Element item = (Element) textAnnotationNodeList.item(i);

open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElementNode.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,11 @@ public void updateSequenceFlowReferences() {
331331
return; // no op!
332332
}
333333
// remove incoming childs...
334-
NodeList incomingSequenceFlows = getElementNode()
335-
.getElementsByTagName(bpmnProcess.getModel().getPrefix(BPMNNS.BPMN2) + "incoming");
334+
// NodeList incomingSequenceFlows = getElementNode()
335+
// .getElementsByTagName(bpmnProcess.getModel().getPrefix(BPMNNS.BPMN2) +
336+
// "incoming");
337+
NodeList incomingSequenceFlows = bpmnProcess.getModel().findElementsByName(getElementNode(), BPMNNS.BPMN2,
338+
"incoming");
336339
for (int i = 0; i < incomingSequenceFlows.getLength(); i++) {
337340
Element item = (Element) incomingSequenceFlows.item(i);
338341
// test if the sequence flow exists...
@@ -346,8 +349,11 @@ public void updateSequenceFlowReferences() {
346349

347350
}
348351
// remove outgoing childs...
349-
NodeList outgoingSequenceFlows = getElementNode()
350-
.getElementsByTagName(bpmnProcess.getModel().getPrefix(BPMNNS.BPMN2) + "outgoing");
352+
// NodeList outgoingSequenceFlows = getElementNode()
353+
// .getElementsByTagName(bpmnProcess.getModel().getPrefix(BPMNNS.BPMN2) +
354+
// "outgoing");
355+
NodeList outgoingSequenceFlows = bpmnProcess.getModel().findElementsByName(getElementNode(),
356+
BPMNNS.BPMN2, "outgoing");
351357
for (int i = 0; i < outgoingSequenceFlows.getLength(); i++) {
352358
Element item = (Element) outgoingSequenceFlows.item(i);
353359
// test if the sequence flow exists...

open-bpmn.metamodel/src/test/java/org/openbpmn/metamodel/test/elements/TestCloneFlowElements.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import org.junit.jupiter.api.Test;
1313
import org.openbpmn.bpmn.BPMNModel;
14+
import org.openbpmn.bpmn.BPMNNS;
1415
import org.openbpmn.bpmn.elements.BPMNProcess;
1516
import org.openbpmn.bpmn.elements.core.BPMNElementNode;
1617
import org.openbpmn.bpmn.exceptions.BPMNModelException;
@@ -58,10 +59,15 @@ public void testCloneDocumentationAndUpdateSequenceFlowRefs() {
5859
clonedTask.setName("Copy of Task 1");
5960

6061
// The id from the documentation must be changed!
61-
NodeList originDocumentationElements = originTask.getElementNode()
62-
.getElementsByTagName("bpmn2:documentation");
63-
NodeList clonedDocumentationElements = clonedTask.getElementNode()
64-
.getElementsByTagName("bpmn2:documentation");
62+
// NodeList originDocumentationElements = originTask.getElementNode()
63+
// .getElementsByTagName("bpmn2:documentation");
64+
NodeList originDocumentationElements = model.findElementsByName(originTask.getElementNode(), BPMNNS.BPMN2,
65+
"documentation");
66+
67+
// NodeList clonedDocumentationElements = clonedTask.getElementNode()
68+
// .getElementsByTagName("bpmn2:documentation");
69+
NodeList clonedDocumentationElements = model.findElementsByName(clonedTask.getElementNode(), BPMNNS.BPMN2,
70+
"documentation");
6571
assertNotNull(clonedDocumentationElements);
6672
assertEquals(1, clonedDocumentationElements.getLength());
6773
// compare IDs
@@ -71,10 +77,15 @@ public void testCloneDocumentationAndUpdateSequenceFlowRefs() {
7177

7278
// next we expect no outgoing and incoming sequenceFlows...
7379

74-
NodeList incomingSequenceFlows = clonedTask.getElementNode()
75-
.getElementsByTagName("bpmn2:incoming");
76-
NodeList outgoingSequenceFlows = clonedTask.getElementNode()
77-
.getElementsByTagName("bpmn2:outgoing");
80+
// NodeList incomingSequenceFlows = clonedTask.getElementNode()
81+
// .getElementsByTagName("bpmn2:incoming");
82+
NodeList incomingSequenceFlows = model.findElementsByName(clonedTask.getElementNode(), BPMNNS.BPMN2,
83+
"incoming");
84+
85+
// NodeList outgoingSequenceFlows = clonedTask.getElementNode()
86+
// .getElementsByTagName("bpmn2:outgoing");
87+
NodeList outgoingSequenceFlows = model.findElementsByName(clonedTask.getElementNode(),
88+
BPMNNS.BPMN2, "outgoing");
7889

7990
assertEquals(0, incomingSequenceFlows.getLength());
8091
assertEquals(0, outgoingSequenceFlows.getLength());

0 commit comments

Comments
 (0)