Skip to content

Commit

Permalink
Implement ExpandedNodeId.parse without NodeId.parse
Browse files Browse the repository at this point in the history
This new implementation also fixes a bug when parsing a String identifier that
contains additional semicolons.

fixes #976
  • Loading branch information
kevinherron committed May 4, 2022
1 parent d0e6f8a commit e1482f4
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 15 deletions.
Expand Up @@ -565,24 +565,56 @@ public String toParseableString() {
*/
public static ExpandedNodeId parse(String s) {
try {
String[] parts = s.split(";");

NodeId nodeId = NodeId.parse(parts[parts.length - 1]);

UInteger serverIndex = UInteger.MIN;
if (s.startsWith("svr=")) {
int endIndex = s.indexOf(";");
serverIndex = uint(Integer.parseInt(s.substring(4, endIndex)));
s = s.substring(endIndex + 1);
}

UShort namespaceIndex = UShort.MIN;
String namespaceUri = null;
Object identifier = nodeId.getIdentifier();

for (String part : parts) {
String[] ss = part.split("=", 2);
if ("svr".equals(ss[0])) {
serverIndex = uint(Integer.parseInt(ss[1]));
} else if ("ns".equals(ss[0])) {
namespaceIndex = ushort(Integer.parseInt(ss[1]));
} else if ("nsu".equals(ss[0])) {
namespaceUri = ss[1];
}
if (s.startsWith("ns=")) {
int endIndex = s.indexOf(";");
namespaceIndex = ushort(Integer.parseInt(s.substring(3, endIndex)));
s = s.substring(endIndex + 1);
} else if (s.startsWith("nsu=")) {
int endIndex = s.indexOf(";");
namespaceUri = s.substring(4, endIndex);
s = s.substring(endIndex + 1);
}

Object identifier;
String type = s.substring(0, 2);
String id = s.substring(2);

switch (type) {
case "i=":
try {
identifier = uint(Long.parseLong(id));
} catch (NumberFormatException e) {
throw new UaRuntimeException(StatusCodes.Bad_NodeIdInvalid, e);
}
break;
case "s=":
identifier = id;
break;
case "g=":
try {
identifier = UUID.fromString(id);
} catch (IllegalArgumentException e) {
throw new UaRuntimeException(StatusCodes.Bad_NodeIdInvalid, e);
}
break;
case "b=":
try {
identifier = ByteString.of(DatatypeConverter.parseBase64Binary(id));
} catch (IllegalArgumentException e) {
throw new UaRuntimeException(StatusCodes.Bad_NodeIdInvalid, e);
}
break;
default:
throw new UaRuntimeException(StatusCodes.Bad_NodeIdInvalid);
}

return new ExpandedNodeId(namespaceIndex, namespaceUri, identifier, serverIndex);
Expand Down
Expand Up @@ -179,6 +179,16 @@ public void parseNamespaceUriContainingEquals() {
assertEquals(xni.getIdentifier(), uint(85));
}

@Test
public void parseIdentifierContainingSemiColons() {
ExpandedNodeId xni = ExpandedNodeId.parse(
"nsu=http://foo.com/bar;s=O=::/#pc;B=::/#pc;S=pc;"
);

assertEquals(xni.getNamespaceUri(), "http://foo.com/bar");
assertEquals(xni.getIdentifier(), "O=::/#pc;B=::/#pc;S=pc;");
}

@Test
public void reindex() {
NamespaceTable namespaceTable = new NamespaceTable();
Expand Down
Expand Up @@ -183,4 +183,12 @@ public void testExpandedWithNamespaceTable() {
assertEquals(xni.getNamespaceUri(), "urn:test");
}

@Test
public void parseIdentifierContainingSemiColons() {
NodeId nodeId = NodeId.parse("ns=14;s=O=::/#pc;B=::/#pc;S=pc;");

assertEquals(nodeId.getNamespaceIndex(), ushort(14));
assertEquals(nodeId.getIdentifier(), "O=::/#pc;B=::/#pc;S=pc;");
}

}

0 comments on commit e1482f4

Please sign in to comment.