Class LazyClientDataTypeTree
DataTypeTree that resolves types on demand by browsing inverse HasSubtype
references.
Unlike DataTypeTreeBuilder which eagerly builds the entire tree by forward browsing
from NodeIds0.BaseDataType, this implementation starts with only the root type and
resolves additional types lazily when they are queried.
This approach is useful when servers don't support recursive forward browsing of the DataType hierarchy or when only a subset of types is needed.
Thread Safety
This implementation is thread-safe. All read operations acquire a read lock and all modifications acquire a write lock. However, note that type resolution (which includes network I/O to browse and read from the server) is performed while holding the write lock. This means that concurrent threads attempting to resolve different types will be serialized. Once a type is resolved, later lookups only require the read lock and can proceed concurrently.
Resolution Behavior
Resolution errors (e.g., network failures, non-existent types) do not cause exceptions to be
thrown from query methods like getDataType(NodeId). Instead, null is returned.
Once a resolution attempt has failed, it will not be retried unless clearFailedResolutions() is called.
Namespace Table
This tree caches a copy of the server's NamespaceTable for converting ExpandedNodeIds during browse operations. If the
server's namespace array changes (e.g., after a reconnection or dynamic namespace registration),
call invalidateNamespaceTable() or refreshNamespaceTable() to update the cached
copy.
-
Nested Class Summary
Nested classes/interfaces inherited from class org.eclipse.milo.opcua.sdk.core.typetree.TypeTree
org.eclipse.milo.opcua.sdk.core.typetree.TypeTree.Type -
Field Summary
Fields inherited from class org.eclipse.milo.opcua.sdk.core.typetree.TypeTree
tree, types -
Constructor Summary
ConstructorsConstructorDescriptionLazyClientDataTypeTree(OpcUaClient client) Create a newLazyClientDataTypeTreewith onlyNodeIds0.BaseDataTypeinitially loaded.LazyClientDataTypeTree(OpcUaClient client, org.eclipse.milo.opcua.stack.core.util.Tree<org.eclipse.milo.opcua.sdk.core.typetree.DataType> preSeededTree) Create a newLazyClientDataTypeTreewith a pre-seeded tree. -
Method Summary
Modifier and TypeMethodDescriptionvoidClear failed resolution attempts, allowing retry.booleancontainsType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId typeId) Class<?>getBackingClass(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) @Nullable org.eclipse.milo.opcua.stack.core.types.builtin.NodeIdgetBinaryEncodingId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) org.eclipse.milo.opcua.stack.core.OpcUaDataTypegetBuiltinType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) @Nullable org.eclipse.milo.opcua.sdk.core.typetree.DataTypegetDataType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) @Nullable org.eclipse.milo.opcua.stack.core.types.structured.DataTypeDefinitiongetDataTypeDefinition(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) @Nullable org.eclipse.milo.opcua.stack.core.types.builtin.NodeIdgetJsonEncodingId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) org.eclipse.milo.opcua.stack.core.util.Tree<org.eclipse.milo.opcua.sdk.core.typetree.DataType>getRoot()Get a snapshot of the root of the underlyingTreestructure.@Nullable org.eclipse.milo.opcua.stack.core.util.Tree<org.eclipse.milo.opcua.sdk.core.typetree.DataType>getTreeNode(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) @Nullable org.eclipse.milo.opcua.sdk.core.typetree.DataTypegetType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId nodeId) @Nullable org.eclipse.milo.opcua.stack.core.types.builtin.NodeIdgetXmlEncodingId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) voidInvalidate the cachedNamespaceTable, causing it to be re-read on next use.booleanisAssignable(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId, Class<?> clazz) booleanisEnumType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) booleanisResolved(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId typeId) Check if a type has been resolved/loaded without triggering resolution.booleanisStructType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) booleanisSubtypeOf(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId typeId, org.eclipse.milo.opcua.stack.core.types.builtin.NodeId superTypeId) voidRefresh the cachedNamespaceTableimmediately by reading it from the server.Methods inherited from class org.eclipse.milo.opcua.sdk.core.typetree.TypeTree
isSubtypeOf, isSubtypeOf, isSubtypeOf
-
Constructor Details
-
LazyClientDataTypeTree
Create a newLazyClientDataTypeTreewith onlyNodeIds0.BaseDataTypeinitially loaded.- Parameters:
client- a connectedOpcUaClient.
-
LazyClientDataTypeTree
public LazyClientDataTypeTree(OpcUaClient client, org.eclipse.milo.opcua.stack.core.util.Tree<org.eclipse.milo.opcua.sdk.core.typetree.DataType> preSeededTree) Create a newLazyClientDataTypeTreewith a pre-seeded tree.This constructor supports preloading known types (e.g., namespace 0 types from a code generator) to reduce the number of lazy resolutions needed.
- Parameters:
client- a connectedOpcUaClient.preSeededTree- a pre-built tree containing known types.
-
-
Method Details
-
invalidateNamespaceTable
public void invalidateNamespaceTable()Invalidate the cachedNamespaceTable, causing it to be re-read on next use.Call this method when the server's namespace array may have changed (e.g., after a reconnection or when namespaces are dynamically registered on the server).
- See Also:
-
refreshNamespaceTable
public void refreshNamespaceTable() throws org.eclipse.milo.opcua.stack.core.UaExceptionRefresh the cachedNamespaceTableimmediately by reading it from the server.Unlike
invalidateNamespaceTable(), this method reads the namespace table immediately rather than deferring until the next type resolution.- Throws:
org.eclipse.milo.opcua.stack.core.UaException- if reading the namespace table fails.- See Also:
-
isResolved
public boolean isResolved(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId typeId) Check if a type has been resolved/loaded without triggering resolution.- Parameters:
typeId- theNodeIdto check.- Returns:
trueif the type is already loaded in the tree.
-
clearFailedResolutions
public void clearFailedResolutions()Clear failed resolution attempts, allowing retry.When a type resolution fails (e.g., due to network errors or non-existent types), the failure is recorded to avoid repeated failed attempts. This method clears those records, allowing later queries for those types to attempt resolution again.
This is useful after transient network issues have been resolved or when the server's type system may have changed.
-
getRoot
public org.eclipse.milo.opcua.stack.core.util.Tree<org.eclipse.milo.opcua.sdk.core.typetree.DataType> getRoot()Get a snapshot of the root of the underlyingTreestructure.Because this tree is lazily populated, returning the live tree would expose callers to potential concurrent modification during traversal. Instead, this method returns a deep copy (snapshot) of the current tree state, taken under a read lock.
The snapshot reflects the types that have been resolved at the time of the call. Types resolved after the snapshot is taken will not appear in the returned tree.
Note: The
Treestructure is copied, but the containedDataTypeinstances are shared references. This is safe becauseDataTypeinstances are effectively immutable.- Overrides:
getRootin classorg.eclipse.milo.opcua.sdk.core.typetree.TypeTree<org.eclipse.milo.opcua.sdk.core.typetree.DataType>- Returns:
- a snapshot copy of the root node of the underlying
Treestructure.
-
containsType
public boolean containsType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId typeId) - Overrides:
containsTypein classorg.eclipse.milo.opcua.sdk.core.typetree.TypeTree<org.eclipse.milo.opcua.sdk.core.typetree.DataType>
-
getType
public @Nullable org.eclipse.milo.opcua.sdk.core.typetree.DataType getType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId nodeId) - Overrides:
getTypein classorg.eclipse.milo.opcua.sdk.core.typetree.TypeTree<org.eclipse.milo.opcua.sdk.core.typetree.DataType>
-
getBackingClass
- Overrides:
getBackingClassin classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
getBuiltinType
public org.eclipse.milo.opcua.stack.core.OpcUaDataType getBuiltinType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
getBuiltinTypein classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
getDataType
public @Nullable org.eclipse.milo.opcua.sdk.core.typetree.DataType getDataType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
getDataTypein classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
getBinaryEncodingId
public @Nullable org.eclipse.milo.opcua.stack.core.types.builtin.NodeId getBinaryEncodingId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
getBinaryEncodingIdin classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
getXmlEncodingId
public @Nullable org.eclipse.milo.opcua.stack.core.types.builtin.NodeId getXmlEncodingId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
getXmlEncodingIdin classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
getJsonEncodingId
public @Nullable org.eclipse.milo.opcua.stack.core.types.builtin.NodeId getJsonEncodingId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
getJsonEncodingIdin classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
getDataTypeDefinition
public @Nullable org.eclipse.milo.opcua.stack.core.types.structured.DataTypeDefinition getDataTypeDefinition(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
getDataTypeDefinitionin classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
isAssignable
public boolean isAssignable(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId, Class<?> clazz) - Overrides:
isAssignablein classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
isEnumType
public boolean isEnumType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
isEnumTypein classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
isStructType
public boolean isStructType(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
isStructTypein classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
getTreeNode
public @Nullable org.eclipse.milo.opcua.stack.core.util.Tree<org.eclipse.milo.opcua.sdk.core.typetree.DataType> getTreeNode(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId dataTypeId) - Overrides:
getTreeNodein classorg.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree
-
isSubtypeOf
public boolean isSubtypeOf(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId typeId, org.eclipse.milo.opcua.stack.core.types.builtin.NodeId superTypeId) - Overrides:
isSubtypeOfin classorg.eclipse.milo.opcua.sdk.core.typetree.TypeTree<org.eclipse.milo.opcua.sdk.core.typetree.DataType>
-