Skip to content

Commit

Permalink
~ WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinherron committed Mar 17, 2024
1 parent 9570aea commit d0ea287
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,19 @@ public void structuresHaveDataTypeDefinitions() {
});
}

@Test
void testIsAbstractAttribute() {
DataType baseDataType = dataTypeTree.getType(NodeIds.BaseDataType);
assertNotNull(baseDataType);
assertTrue(baseDataType.isAbstract());

DataType structureType = dataTypeTree.getType(NodeIds.Structure);
assertNotNull(structureType);
assertTrue(structureType.isAbstract());

DataType xvType = dataTypeTree.getType(NodeIds.XVType);
assertNotNull(xvType);
assertFalse(xvType.isAbstract());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ class ClientDataType implements DataType {
private final NodeId xmlEncodingId;
private final NodeId jsonEncodingId;
private final DataTypeDefinition dataTypeDefinition;
private final Boolean isAbstract;

public ClientDataType(
QualifiedName browseName,
NodeId nodeId,
NodeId binaryEncodingId,
NodeId xmlEncodingId,
NodeId jsonEncodingId,
DataTypeDefinition dataTypeDefinition
DataTypeDefinition dataTypeDefinition, Boolean isAbstract
) {

this.browseName = browseName;
Expand All @@ -54,6 +55,7 @@ public ClientDataType(
this.xmlEncodingId = xmlEncodingId;
this.jsonEncodingId = jsonEncodingId;
this.dataTypeDefinition = dataTypeDefinition;
this.isAbstract = isAbstract;
}

@Override
Expand Down Expand Up @@ -86,6 +88,11 @@ public NodeId getNodeId() {
return dataTypeDefinition;
}

@Override
public Boolean isAbstract() {
return isAbstract;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand All @@ -96,7 +103,8 @@ public boolean equals(Object o) {
Objects.equals(binaryEncodingId, dataType.binaryEncodingId) &&
Objects.equals(xmlEncodingId, dataType.xmlEncodingId) &&
Objects.equals(jsonEncodingId, dataType.jsonEncodingId) &&
Objects.equals(dataTypeDefinition, dataType.dataTypeDefinition);
Objects.equals(dataTypeDefinition, dataType.dataTypeDefinition) &&
Objects.equals(isAbstract, dataType.isAbstract);
}

@Override
Expand All @@ -107,7 +115,8 @@ public int hashCode() {
binaryEncodingId,
xmlEncodingId,
jsonEncodingId,
dataTypeDefinition
dataTypeDefinition,
isAbstract
);
}

Expand All @@ -120,6 +129,7 @@ public String toString() {
.add("xmlEncodingId=" + xmlEncodingId)
.add("jsonEncodingId=" + jsonEncodingId)
.add("dataTypeDefinition=" + dataTypeDefinition)
.add("isAbstract=" + isAbstract)
.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public static DataTypeTree build(OpcUaClient client) throws UaException {
null,
null,
null,
null
null,
true
)
);

Expand Down Expand Up @@ -153,23 +154,24 @@ private static void addChildren(
maxNodesPerBrowse
);

List<DataTypeDefinition> dataTypeDefinitions = readDataTypeDefinitions(
List<Attributes> dataTypeAttributes = readDataTypeAttributes(
client,
dataTypeIds,
maxNodesPerRead
);

assert subtypes.size() == dataTypeIds.size() &&
subtypes.size() == encodingReferences.size() &&
subtypes.size() == dataTypeDefinitions.size();
subtypes.size() == dataTypeAttributes.size();

var dataTypes = new ArrayList<ClientDataType>();

for (int j = 0; j < subtypes.size(); j++) {
QualifiedName browseName = subtypes.get(j).getBrowseName();
NodeId dataTypeId = dataTypeIds.get(j);
List<ReferenceDescription> encodings = encodingReferences.get(j);
DataTypeDefinition dataTypeDefinition = dataTypeDefinitions.get(j);
DataTypeDefinition dataTypeDefinition = dataTypeAttributes.get(j).definition;
Boolean isAbstract = dataTypeAttributes.get(j).isAbstract;

NodeId binaryEncodingId = null;
NodeId xmlEncodingId = null;
Expand Down Expand Up @@ -200,7 +202,8 @@ private static void addChildren(
binaryEncodingId,
xmlEncodingId,
jsonEncodingId,
dataTypeDefinition
dataTypeDefinition,
isAbstract
);

dataTypes.add(dataType);
Expand Down Expand Up @@ -269,7 +272,7 @@ private static List<List<ReferenceDescription>> browseEncodings(
return browseWithOperationLimits(client, browseDescriptions, maxNodesPerBrowse);
}

private static List<@Nullable DataTypeDefinition> readDataTypeDefinitions(
private static List<@Nullable Attributes> readDataTypeAttributes(
OpcUaClient client,
List<NodeId> dataTypeIds,
UInteger maxNodesPerRead
Expand All @@ -279,36 +282,67 @@ private static List<List<ReferenceDescription>> browseEncodings(
return List.of();
}

List<ReadValueId> readValueIds = dataTypeIds.stream()
.map(dataTypeId ->
var readValueIds = new ArrayList<ReadValueId>();

for (NodeId dataTypeId : dataTypeIds) {
readValueIds.add(
new ReadValueId(
dataTypeId,
AttributeId.IsAbstract.uid(),
null,
QualifiedName.NULL_VALUE
)
);
readValueIds.add(
new ReadValueId(
dataTypeId,
AttributeId.DataTypeDefinition.uid(),
null,
QualifiedName.NULL_VALUE
)
)
.collect(Collectors.toList());
);
}

return readWithOperationLimits(client, readValueIds, maxNodesPerRead).stream()
.map(value -> {
if (value.getStatusCode() != null && value.getStatusCode().isGood()) {
Object o = value.getValue().getValue();
if (o instanceof ExtensionObject) {
Object decoded = ((ExtensionObject) o).decode(
client.getStaticEncodingContext()
);

return (DataTypeDefinition) decoded;
} else {
return null;
}
} else {
// OPC UA 1.03 and prior servers will return Bad_AttributeIdInvalid
return null;
var attributes = new ArrayList<Attributes>();

List<DataValue> values = readWithOperationLimits(client, readValueIds, maxNodesPerRead);

for (int i = 0; i < values.size(); i += 2) {
DataValue isAbstractValue = values.get(i);
DataValue definitionValue = values.get(i + 1);

Boolean isAbstract = false;
DataTypeDefinition definition = null;

if (isAbstractValue.getStatusCode() != null && isAbstractValue.getStatusCode().isGood()) {
isAbstract = (Boolean) isAbstractValue.getValue().getValue();
}

if (definitionValue.getStatusCode() != null && definitionValue.getStatusCode().isGood()) {
Object o = definitionValue.getValue().getValue();
if (o instanceof ExtensionObject) {
Object decoded = ((ExtensionObject) o).decode(
client.getStaticEncodingContext()
);

definition = (DataTypeDefinition) decoded;
}
})
.collect(Collectors.toList());
}

attributes.add(new Attributes(isAbstract, definition));
}

return attributes;
}

private static class Attributes {
final Boolean isAbstract;
final DataTypeDefinition definition;

private Attributes(Boolean isAbstract, DataTypeDefinition definition) {
this.isAbstract = isAbstract;
this.definition = definition;
}
}

private static UInteger[] readOperationLimits(OpcUaClient client) throws UaException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,11 @@ public interface DataType extends TypeTree.Type {
*/
@Nullable DataTypeDefinition getDataTypeDefinition();

/**
* Get whether this DataType is abstract.
*
* @return {@code true} if this DataType is abstract.
*/
Boolean isAbstract();

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import org.eclipse.milo.opcua.sdk.server.OpcUaServer;
import org.eclipse.milo.opcua.sdk.server.Session;
import org.eclipse.milo.opcua.sdk.server.nodes.UaMethodNode;
import org.eclipse.milo.opcua.sdk.server.typetree.DataTypeTreeBuilder;
import org.eclipse.milo.opcua.stack.core.AttributeId;
import org.eclipse.milo.opcua.stack.core.StatusCodes;
import org.eclipse.milo.opcua.stack.core.UaException;
Expand Down Expand Up @@ -103,11 +102,7 @@ public final CallMethodResult invoke(AccessContext accessContext, CallMethodRequ
.orElse(NodeId.NULL_VALUE);

DataType type = dataTypeTree.getType(argDataTypeId);

// TODO better way to determine if a type is abstract...
// add to DataType? dataTypeTree.isAbstract()?
boolean isAbstract = type != null &&
((DataTypeTreeBuilder.ServerDataType) type).isAbstract();
boolean isAbstract = type != null && type.isAbstract();

if (isAbstract) {
dataTypeMatch = dataTypeTree.isSubtypeOf(typeId, argDataTypeId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private static void addChildren(Tree<DataType> tree, OpcUaServer server) {
}
}

public static class ServerDataType implements DataType {
private static class ServerDataType implements DataType {

private final UaDataTypeNode node;
private final @Nullable NodeId binaryEncodingId;
Expand Down Expand Up @@ -146,7 +146,8 @@ public DataTypeDefinition getDataTypeDefinition() {
return node.getDataTypeDefinition();
}

public boolean isAbstract() {
@Override
public Boolean isAbstract() {
return node.getIsAbstract();
}

Expand Down

0 comments on commit d0ea287

Please sign in to comment.