Skip to content

Commit

Permalink
WIP OpcUaJsonDecoder
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinherron committed Jul 7, 2022
1 parent 7084d22 commit 5a7941a
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 1 deletion.
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.ULong;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UShort;
import org.eclipse.milo.opcua.stack.core.types.enumerated.IdType;

import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ubyte;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
Expand Down Expand Up @@ -573,7 +574,91 @@ public XmlElement readXmlElement(String field) throws UaSerializationException {

@Override
public NodeId readNodeId(String field) throws UaSerializationException {
return null;
try {
if (field != null) {
String nextName = jsonReader.nextName();
if (!field.equals(nextName)) {
throw new UaSerializationException(
StatusCodes.Bad_DecodingError,
String.format("readNodeId: %s != %s", field, nextName)
);
}
}

IdType idType = IdType.Numeric;
int namespaceIndex = 0;
Object id = null;

try {
jsonReader.beginObject();

while (jsonReader.peek() == JsonToken.NAME) {
String propertyName = jsonReader.nextName();

switch (propertyName) {
case "IdType": {
int value = jsonReader.nextInt();
idType = IdType.from(value);
if (idType == null) {
throw new UaSerializationException(
StatusCodes.Bad_DecodingError,
"readNodeId: invalid IdType: " + value
);
}
break;
}
case "Id": {
switch (idType) {
case Numeric:
id = uint(jsonReader.nextInt());
break;
case String:
id = jsonReader.nextString();
break;
case Guid:
id = UUID.fromString(jsonReader.nextString());
break;
case Opaque:
id = ByteString.of(Base64.getDecoder().decode(jsonReader.nextString()));
break;
}
break;
}
case "Namespace": {
namespaceIndex = jsonReader.nextInt();
break;
}
}
}

jsonReader.endObject();

if (id == null) {
throw new UaSerializationException(StatusCodes.Bad_DecodingError, "id == null");
} else {
switch (idType) {
case Numeric:
assert id instanceof UInteger;
return new NodeId(namespaceIndex, (UInteger) id);
case String:
assert id instanceof String;
return new NodeId(namespaceIndex, (String) id);
case Guid:
assert id instanceof UUID;
return new NodeId(namespaceIndex, (UUID) id);
case Opaque:
assert id instanceof ByteString;
return new NodeId(namespaceIndex, (ByteString) id);
default:
throw new UaSerializationException(StatusCodes.Bad_DecodingError, "idType: " + idType);
}
}
} catch (IOException e) {
throw new UaSerializationException(StatusCodes.Bad_DecodingError, e);
}
} catch (IOException e) {
throw new UaSerializationException(StatusCodes.Bad_DecodingError, e);
}
}

@Override
Expand Down
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.milo.opcua.stack.core.UaSerializationException;
import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString;
import org.eclipse.milo.opcua.stack.core.types.builtin.DateTime;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.XmlElement;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UByte;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
Expand Down Expand Up @@ -428,6 +429,92 @@ void readXmlElement() throws IOException {
decoder.jsonReader.endObject();
}

@Test
void readNodeId() throws IOException {
var decoder = new OpcUaJsonDecoder(new StringReader(""));

// IdType == UInt32, Namespace = 0
var nodeId = new NodeId(0, 0);
decoder.reset(new StringReader("{\"Id\":0}"));
assertEquals(nodeId, decoder.readNodeId(null));

// IdType == UInt32, Namespace != 0
nodeId = new NodeId(1, 0);
decoder.reset(new StringReader("{\"Id\":0,\"Namespace\":1}"));
assertEquals(nodeId, decoder.readNodeId(null));

// IdType == String, Namespace = 0
nodeId = new NodeId(0, "foo");
decoder.reset(new StringReader("{\"IdType\":1,\"Id\":\"foo\"}"));
assertEquals(nodeId, decoder.readNodeId(null));

// IdType == String, Namespace != 0
nodeId = new NodeId(1, "foo");
decoder.reset(new StringReader("{\"IdType\":1,\"Id\":\"foo\",\"Namespace\":1}"));
assertEquals(nodeId, decoder.readNodeId(null));

// IdType == Guid, Namespace = 0
UUID uuid = UUID.randomUUID();
nodeId = new NodeId(0, uuid);
decoder.reset(new StringReader("{\"IdType\":2,\"Id\":\"" + uuid.toString().toUpperCase() + "\"}"));
assertEquals(nodeId, decoder.readNodeId(null));

// IdType == Guid, Namespace != 0
nodeId = new NodeId(1, uuid);
decoder.reset(new StringReader("{\"IdType\":2,\"Id\":\"" + uuid.toString().toUpperCase() + "\",\"Namespace\":1}"));
assertEquals(nodeId, decoder.readNodeId(null));

// IdType == ByteString, Namespace = 0
ByteString bs = ByteString.of(randomBytes(16));
nodeId = new NodeId(0, bs);
decoder.reset(new StringReader("{\"IdType\":3,\"Id\":\"" + Base64.getEncoder().encodeToString(bs.bytesOrEmpty()) + "\"}"));
assertEquals(nodeId, decoder.readNodeId(null));

// IdType == ByteString, Namespace != 0
nodeId = new NodeId(1, bs);
decoder.reset(new StringReader("{\"IdType\":3,\"Id\":\"" + Base64.getEncoder().encodeToString(bs.bytesOrEmpty()) + "\",\"Namespace\":1}"));
assertEquals(nodeId, decoder.readNodeId(null));

nodeId = new NodeId(0, 0);
decoder.reset(new StringReader("{\"foo\":{\"Id\":0}}"));
decoder.jsonReader.beginObject();
assertEquals(nodeId, decoder.readNodeId("foo"));
decoder.jsonReader.endObject();
}

@Test
void readExpandedNodeId() throws IOException {}

@Test
void readStatusCode() throws IOException {}

@Test
void readQualifiedName() throws IOException {}

@Test
void readLocalizedText() throws IOException {}

@Test
void readExtensionObject() throws IOException {}

@Test
void readDataValue() throws IOException {}

@Test
void readVariant() throws IOException {}

@Test
void readDiagnosticInfo() throws IOException {}

@Test
void readMessage() throws IOException {}

@Test
void readEnum() throws IOException {}

@Test
void readStruct() throws IOException {}

private static byte[] randomBytes(int length) {
var random = new Random();
var bs = new byte[length];
Expand Down

0 comments on commit 5a7941a

Please sign in to comment.