diff --git a/milo-examples/client-examples/src/main/java/org/eclipse/milo/examples/client/LegacyDataTypeDictionaryExample.java b/milo-examples/client-examples/src/main/java/org/eclipse/milo/examples/client/LegacyDataTypeDictionaryExample.java
index df451d9f3..a22f18a21 100644
--- a/milo-examples/client-examples/src/main/java/org/eclipse/milo/examples/client/LegacyDataTypeDictionaryExample.java
+++ b/milo-examples/client-examples/src/main/java/org/eclipse/milo/examples/client/LegacyDataTypeDictionaryExample.java
@@ -12,8 +12,8 @@
import java.util.concurrent.CompletableFuture;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
-import org.eclipse.milo.opcua.sdk.client.OpcUaClient.DefaultDataTypeManagerInitializer;
import org.eclipse.milo.opcua.sdk.client.dtd.LegacyDataTypeManagerInitializer;
+import org.eclipse.milo.opcua.sdk.client.typetree.DataTypeManagerFactory;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject;
@@ -27,7 +27,8 @@
* specification.
*
*
This was the default (and only supported mechanism) in Milo 0.6.x and earlier. Milo 1.x now
- * uses the DataTypeDefinition attribute instead via {@link DefaultDataTypeManagerInitializer}.
+ * uses the DataTypeDefinition attribute instead via {@link
+ * DataTypeManagerFactory.DefaultInitializer}.
*
*
Requires a server that still supports DataTypeDictionary, such as the Unified Automation C++
* demo server, which this example is configured for by default.
@@ -42,7 +43,8 @@ public static void main(String[] args) throws Exception {
@Override
public void run(OpcUaClient client, CompletableFuture future) throws Exception {
- client.setDataTypeManagerInitializer(new LegacyDataTypeManagerInitializer(client));
+ client.setDynamicDataTypeManagerFactory(
+ DataTypeManagerFactory.eager(new LegacyDataTypeManagerInitializer(client)));
client.connect();
diff --git a/opc-ua-sdk/dtd-reader/src/main/java/org/eclipse/milo/opcua/sdk/client/dtd/LegacyDataTypeManagerInitializer.java b/opc-ua-sdk/dtd-reader/src/main/java/org/eclipse/milo/opcua/sdk/client/dtd/LegacyDataTypeManagerInitializer.java
index 238c15c09..3786e7581 100644
--- a/opc-ua-sdk/dtd-reader/src/main/java/org/eclipse/milo/opcua/sdk/client/dtd/LegacyDataTypeManagerInitializer.java
+++ b/opc-ua-sdk/dtd-reader/src/main/java/org/eclipse/milo/opcua/sdk/client/dtd/LegacyDataTypeManagerInitializer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 the Eclipse Milo Authors
+ * Copyright (c) 2025 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
@@ -12,6 +12,7 @@
import java.util.List;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.client.typetree.DataTypeManagerFactory;
import org.eclipse.milo.opcua.sdk.core.dtd.generic.StructCodec;
import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
import org.eclipse.milo.opcua.stack.core.NamespaceTable;
@@ -19,7 +20,15 @@
import org.eclipse.milo.opcua.stack.core.types.DataTypeDictionary;
import org.eclipse.milo.opcua.stack.core.types.DataTypeManager;
-public class LegacyDataTypeManagerInitializer implements OpcUaClient.DataTypeManagerInitializer {
+/**
+ * A {@link DataTypeManagerFactory.Initializer} that reads legacy DataTypeDictionary information
+ * from the server and registers codecs based on that.
+ *
+ * This is for servers that support the legacy (OPC UA <= 1.03) DataTypeDictionary mechanism.
+ *
+ * @see DataTypeManagerFactory#eager(DataTypeManagerFactory.Initializer)
+ */
+public class LegacyDataTypeManagerInitializer implements DataTypeManagerFactory.Initializer {
private final OpcUaClient client;
private final BinaryCodecFactory codecFactory;
diff --git a/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeFactoryTest.java b/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeFactoryTest.java
new file mode 100644
index 000000000..64aa2cce6
--- /dev/null
+++ b/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeFactoryTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+
+import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
+import org.eclipse.milo.opcua.sdk.test.AbstractClientServerTest;
+import org.eclipse.milo.opcua.stack.core.NodeIds;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public class DataTypeTreeFactoryTest extends AbstractClientServerTest {
+
+ @Test
+ void defaultFactoryCreatesEagerTree() throws Exception {
+ DataTypeTree tree = client.getDataTypeTree();
+
+ assertNotNull(tree);
+ assertNotNull(tree.getDataType(NodeIds.Int32));
+ assertNotNull(tree.getDataType(NodeIds.String));
+ assertNotNull(tree.getDataType(NodeIds.XVType));
+ }
+
+ @Test
+ void setDataTypeTreeFactoryToLazy() throws Exception {
+ client.setDataTypeTreeFactory(DataTypeTreeFactory.lazy());
+
+ DataTypeTree tree = client.getDataTypeTree();
+
+ assertNotNull(tree);
+ assertInstanceOf(LazyClientDataTypeTree.class, tree);
+ assertNotNull(tree.getDataType(NodeIds.Int32));
+ assertNotNull(tree.getDataType(NodeIds.String));
+ assertNotNull(tree.getDataType(NodeIds.XVType));
+ }
+
+ @Test
+ void setDataTypeTreeFactoryResetsCache() throws Exception {
+ client.setDataTypeTreeFactory(DataTypeTreeFactory.eager());
+
+ DataTypeTree tree1 = client.getDataTypeTree();
+ assertNotNull(tree1);
+
+ client.setDataTypeTreeFactory(DataTypeTreeFactory.lazy());
+
+ DataTypeTree tree2 = client.getDataTypeTree();
+ assertNotNull(tree2);
+
+ assertNotSame(tree1, tree2);
+ assertInstanceOf(LazyClientDataTypeTree.class, tree2);
+ }
+
+ @Test
+ void customFactoryIsUsed() throws Exception {
+ var customTree = new LazyClientDataTypeTree(client);
+
+ client.setDataTypeTreeFactory(c -> customTree);
+
+ DataTypeTree tree = client.getDataTypeTree();
+
+ assertNotNull(tree);
+ assertInstanceOf(LazyClientDataTypeTree.class, tree);
+ }
+}
diff --git a/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTreeTest.java b/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTreeTest.java
new file mode 100644
index 000000000..ad31b00fd
--- /dev/null
+++ b/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTreeTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import org.eclipse.milo.opcua.sdk.core.typetree.AbstractDataTypeTreeTest;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataType;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
+import org.eclipse.milo.opcua.stack.core.NodeIds;
+import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.util.Tree;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Integration tests for {@link LazyClientDataTypeTree}.
+ *
+ *
Extends {@link AbstractDataTypeTreeTest} to inherit all standard DataTypeTree tests, plus
+ * additional tests specific to lazy loading behavior.
+ */
+public class LazyClientDataTypeTreeTest extends AbstractDataTypeTreeTest {
+
+ @Override
+ protected DataTypeTree getDataTypeTree() {
+ return new LazyClientDataTypeTree(client);
+ }
+
+ @Test
+ void initiallyOnlyContainsBaseDataType() {
+ // Create a fresh tree to test the initial state
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // BaseDataType should be resolved (it's the root)
+ assertTrue(freshTree.isResolved(NodeIds.BaseDataType));
+
+ // Other types should not be resolved yet
+ assertFalse(freshTree.isResolved(NodeIds.Int32));
+ assertFalse(freshTree.isResolved(NodeIds.String));
+ assertFalse(freshTree.isResolved(NodeIds.Structure));
+ }
+
+ @Test
+ void resolvesTypeOnDemand() {
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // Int32 not resolved initially
+ assertFalse(freshTree.isResolved(NodeIds.Int32));
+
+ // Query Int32 - this should trigger resolution
+ DataType int32Type = freshTree.getDataType(NodeIds.Int32);
+ assertNotNull(int32Type);
+ assertEquals("Int32", int32Type.getBrowseName().name());
+
+ // Now Int32 should be resolved
+ assertTrue(freshTree.isResolved(NodeIds.Int32));
+
+ // Ancestors should also be resolved (Integer, Number, BaseDataType)
+ assertTrue(freshTree.isResolved(NodeIds.Integer));
+ assertTrue(freshTree.isResolved(NodeIds.Number));
+ assertTrue(freshTree.isResolved(NodeIds.BaseDataType));
+ }
+
+ @Test
+ void resolvesStructuredTypes() {
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // Query a structured type
+ DataType xvType = freshTree.getDataType(NodeIds.XVType);
+ assertNotNull(xvType);
+ assertEquals("XVType", xvType.getBrowseName().name());
+
+ // Should have encoding IDs
+ assertNotNull(xvType.getBinaryEncodingId());
+
+ // Should have a DataTypeDefinition
+ assertNotNull(xvType.getDataTypeDefinition());
+
+ // Ancestors should be resolved
+ assertTrue(freshTree.isResolved(NodeIds.Structure));
+ assertTrue(freshTree.isResolved(NodeIds.BaseDataType));
+ }
+
+ @Test
+ void isSubtypeOfWorksWithLazyResolution() {
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // Neither Int32 nor Integer are resolved yet
+ assertFalse(freshTree.isResolved(NodeIds.Int32));
+ assertFalse(freshTree.isResolved(NodeIds.Integer));
+
+ // This should trigger resolution of Int32 and its ancestors
+ assertTrue(freshTree.isSubtypeOf(NodeIds.Int32, NodeIds.Integer));
+ assertTrue(freshTree.isSubtypeOf(NodeIds.Int32, NodeIds.Number));
+ assertTrue(freshTree.isSubtypeOf(NodeIds.Int32, NodeIds.BaseDataType));
+
+ // Int32 is not a subtype of String
+ assertFalse(freshTree.isSubtypeOf(NodeIds.Int32, NodeIds.String));
+ }
+
+ @Test
+ void containsTypeTriggersResolution() {
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // Double not resolved initially
+ assertFalse(freshTree.isResolved(NodeIds.Double));
+
+ // containsType should trigger resolution and return true
+ assertTrue(freshTree.containsType(NodeIds.Double));
+
+ // Now it should be resolved
+ assertTrue(freshTree.isResolved(NodeIds.Double));
+ }
+
+ @Test
+ void cachesResolvedTypes() {
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // First query - triggers resolution
+ DataType first = freshTree.getDataType(NodeIds.Int32);
+ assertNotNull(first);
+
+ // Second query - should return the same result from cache
+ DataType second = freshTree.getDataType(NodeIds.Int32);
+ assertNotNull(second);
+
+ assertEquals(first.getNodeId(), second.getNodeId());
+ assertEquals(first.getBrowseName(), second.getBrowseName());
+ }
+
+ @Test
+ void lazyTreeMatchesEagerTreeForResolvedTypes() throws UaException {
+ DataTypeTree eagerTree = DataTypeTreeBuilder.build(client);
+ var lazyTestTree = new LazyClientDataTypeTree(client);
+
+ // Test a variety of types
+ NodeId[] typesToTest = {
+ NodeIds.Int32,
+ NodeIds.String,
+ NodeIds.Double,
+ NodeIds.DateTime,
+ NodeIds.ByteString,
+ NodeIds.Structure,
+ NodeIds.Enumeration,
+ NodeIds.XVType,
+ NodeIds.Range
+ };
+
+ for (NodeId typeId : typesToTest) {
+ DataType eagerType = eagerTree.getDataType(typeId);
+ DataType lazyType = lazyTestTree.getDataType(typeId);
+
+ if (eagerType != null) {
+ assertNotNull(lazyType, "Lazy tree should resolve type: " + typeId);
+ assertEquals(
+ eagerType.getBrowseName(),
+ lazyType.getBrowseName(),
+ "BrowseName mismatch for " + typeId);
+ assertEquals(
+ eagerType.getBinaryEncodingId(),
+ lazyType.getBinaryEncodingId(),
+ "BinaryEncodingId mismatch for " + typeId);
+ assertEquals(
+ eagerType.getXmlEncodingId(),
+ lazyType.getXmlEncodingId(),
+ "XmlEncodingId mismatch for " + typeId);
+ assertEquals(
+ eagerType.getJsonEncodingId(),
+ lazyType.getJsonEncodingId(),
+ "JsonEncodingId mismatch for " + typeId);
+ assertEquals(
+ eagerType.isAbstract(), lazyType.isAbstract(), "IsAbstract mismatch for " + typeId);
+ }
+ }
+ }
+
+ @Test
+ void diagnosticTestForStructure() throws Exception {
+ // Test that Structure can be resolved
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // BaseDataType should be the only resolved type initially
+ assertTrue(freshTree.isResolved(NodeIds.BaseDataType), "BaseDataType should be pre-loaded");
+ assertFalse(freshTree.isResolved(NodeIds.Structure), "Structure should not be resolved yet");
+
+ // Query Structure - should trigger lazy resolution
+ DataType structureType = freshTree.getType(NodeIds.Structure);
+
+ assertNotNull(structureType, "Structure should be resolved");
+ assertEquals("Structure", structureType.getBrowseName().name());
+ }
+
+ @Test
+ void clearFailedResolutionsAllowsRetry() {
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // Try to resolve a non-existent type
+ NodeId fakeTypeId = new NodeId(999, "FakeDataType");
+ DataType result = freshTree.getDataType(fakeTypeId);
+
+ // Should return null
+ assertTrue(result == null || !freshTree.isResolved(fakeTypeId));
+
+ // Clear failed resolutions
+ freshTree.clearFailedResolutions();
+
+ // Now it can be attempted again (will still fail, but the point is it's retried)
+ result = freshTree.getDataType(fakeTypeId);
+ assertTrue(result == null || !freshTree.isResolved(fakeTypeId));
+ }
+
+ @Test
+ void getRootReturnsSnapshot() {
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // Initially only BaseDataType is in the tree
+ Tree snapshot1 = freshTree.getRoot();
+ var count1 = new AtomicInteger(0);
+ snapshot1.traverseNodes(node -> count1.incrementAndGet());
+ assertEquals(1, count1.get(), "Initial snapshot should only contain BaseDataType");
+
+ // Resolve some types
+ freshTree.getDataType(NodeIds.Int32); // Resolves Int32 -> Integer -> Number -> BaseDataType
+ freshTree.getDataType(NodeIds.String); // Resolves String -> BaseDataType
+
+ // Get a new snapshot - should reflect the resolved types
+ Tree snapshot2 = freshTree.getRoot();
+ var count2 = new AtomicInteger(0);
+ snapshot2.traverseNodes(node -> count2.incrementAndGet());
+ assertTrue(count2.get() > count1.get(), "Second snapshot should contain more types");
+
+ // The first snapshot should be unchanged (it's a copy)
+ var recount1 = new AtomicInteger(0);
+ snapshot1.traverseNodes(node -> recount1.incrementAndGet());
+ assertEquals(count1.get(), recount1.get(), "First snapshot should be unchanged");
+
+ // Verify the snapshots are independent copies (not the same object)
+ assertNotEquals(snapshot1, snapshot2);
+ }
+
+ @Test
+ void getRootSnapshotIsTraversable() {
+ var freshTree = new LazyClientDataTypeTree(client);
+
+ // Resolve a few types to build up the tree
+ freshTree.getDataType(NodeIds.Int32);
+ freshTree.getDataType(NodeIds.Double);
+ freshTree.getDataType(NodeIds.String);
+ freshTree.getDataType(NodeIds.Structure);
+
+ // Get a snapshot and traverse it
+ Tree snapshot = freshTree.getRoot();
+
+ // Verify we can traverse and find expected types
+ var foundInt32 = new AtomicInteger(0);
+ var foundDouble = new AtomicInteger(0);
+ var foundString = new AtomicInteger(0);
+ var foundStructure = new AtomicInteger(0);
+
+ snapshot.traverse(
+ dataType -> {
+ if (NodeIds.Int32.equals(dataType.getNodeId())) foundInt32.incrementAndGet();
+ if (NodeIds.Double.equals(dataType.getNodeId())) foundDouble.incrementAndGet();
+ if (NodeIds.String.equals(dataType.getNodeId())) foundString.incrementAndGet();
+ if (NodeIds.Structure.equals(dataType.getNodeId())) foundStructure.incrementAndGet();
+ });
+
+ assertEquals(1, foundInt32.get(), "Should find Int32 in snapshot");
+ assertEquals(1, foundDouble.get(), "Should find Double in snapshot");
+ assertEquals(1, foundString.get(), "Should find String in snapshot");
+ assertEquals(1, foundStructure.get(), "Should find Structure in snapshot");
+ }
+}
diff --git a/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/SeededLazyClientDataTypeTreeTest.java b/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/SeededLazyClientDataTypeTreeTest.java
new file mode 100644
index 000000000..e57a9fad7
--- /dev/null
+++ b/opc-ua-sdk/integration-tests/src/test/java/org/eclipse/milo/opcua/sdk/client/typetree/SeededLazyClientDataTypeTreeTest.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import org.eclipse.milo.opcua.sdk.core.typetree.AbstractDataTypeTreeTest;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataType;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
+import org.eclipse.milo.opcua.stack.core.NodeIds;
+import org.eclipse.milo.opcua.stack.core.OpcUaDataType;
+import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.util.Tree;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Integration tests for {@link LazyClientDataTypeTree} using a pre-seeded tree.
+ *
+ * Extends {@link AbstractDataTypeTreeTest} to inherit all standard DataTypeTree tests. Unlike
+ * {@link LazyClientDataTypeTreeTest}, this version uses the seed from {@link
+ * LazyClientDataTypeTreeSeed} which pre-populates non-structure types, so they are immediately
+ * resolvable without lazy browsing.
+ */
+public class SeededLazyClientDataTypeTreeTest extends AbstractDataTypeTreeTest {
+
+ @Override
+ protected DataTypeTree getDataTypeTree() {
+ return new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+ }
+
+ @Test
+ void seededTypesAreImmediatelyResolved() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // All types from the seed should be resolved immediately
+ assertTrue(seededTree.isResolved(NodeIds.BaseDataType));
+ assertTrue(seededTree.isResolved(NodeIds.Boolean));
+ assertTrue(seededTree.isResolved(NodeIds.String));
+ assertTrue(seededTree.isResolved(NodeIds.Int32));
+ assertTrue(seededTree.isResolved(NodeIds.Double));
+ assertTrue(seededTree.isResolved(NodeIds.DateTime));
+ assertTrue(seededTree.isResolved(NodeIds.ByteString));
+ assertTrue(seededTree.isResolved(NodeIds.Number));
+ assertTrue(seededTree.isResolved(NodeIds.Integer));
+ assertTrue(seededTree.isResolved(NodeIds.UInteger));
+ assertTrue(seededTree.isResolved(NodeIds.Enumeration));
+ }
+
+ @Test
+ void primitiveTypesAvailableWithoutResolution() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Query primitive types - should return immediately without server browsing
+ DataType int32Type = seededTree.getDataType(NodeIds.Int32);
+ assertNotNull(int32Type);
+ assertEquals("Int32", int32Type.getBrowseName().name());
+
+ DataType stringType = seededTree.getDataType(NodeIds.String);
+ assertNotNull(stringType);
+ assertEquals("String", stringType.getBrowseName().name());
+
+ DataType doubleType = seededTree.getDataType(NodeIds.Double);
+ assertNotNull(doubleType);
+ assertEquals("Double", doubleType.getBrowseName().name());
+ }
+
+ @Test
+ void subTypesAreAvailable() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // String subtypes from the seed
+ assertTrue(seededTree.isResolved(NodeIds.NumericRange));
+ assertTrue(seededTree.isResolved(NodeIds.LocaleId));
+
+ // ByteString subtypes from the seed
+ assertTrue(seededTree.isResolved(NodeIds.Image));
+ assertTrue(seededTree.isResolved(NodeIds.ImageBMP));
+
+ // Number subtypes from the seed
+ assertTrue(seededTree.isResolved(NodeIds.Integer));
+ assertTrue(seededTree.isResolved(NodeIds.UInteger));
+ assertTrue(seededTree.isResolved(NodeIds.Float));
+ }
+
+ @Test
+ void isSubtypeOfWorksForSeededTypes() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Int32 -> Integer -> Number -> BaseDataType
+ assertTrue(seededTree.isSubtypeOf(NodeIds.Int32, NodeIds.Integer));
+ assertTrue(seededTree.isSubtypeOf(NodeIds.Int32, NodeIds.Number));
+ assertTrue(seededTree.isSubtypeOf(NodeIds.Int32, NodeIds.BaseDataType));
+
+ // String -> BaseDataType
+ assertTrue(seededTree.isSubtypeOf(NodeIds.String, NodeIds.BaseDataType));
+
+ // LocaleId -> String -> BaseDataType
+ assertTrue(seededTree.isSubtypeOf(NodeIds.LocaleId, NodeIds.String));
+ assertTrue(seededTree.isSubtypeOf(NodeIds.LocaleId, NodeIds.BaseDataType));
+
+ // Int32 is not a subtype of String
+ assertFalse(seededTree.isSubtypeOf(NodeIds.Int32, NodeIds.String));
+ }
+
+ @Test
+ void enumerationSubtypesAreSeeded() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Enumeration and its subtypes are in the seed
+ assertTrue(seededTree.isResolved(NodeIds.Enumeration));
+ assertTrue(seededTree.isResolved(NodeIds.NodeClass));
+ assertTrue(seededTree.isResolved(NodeIds.ServerState));
+ assertTrue(seededTree.isResolved(NodeIds.RedundancySupport));
+ }
+
+ @Test
+ void seededEnumerationSubtypesHaveDefinitions() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // NodeClass is a seeded enum subtype with an EnumDefinition
+ DataType nodeClassType = seededTree.getDataType(NodeIds.NodeClass);
+ assertNotNull(nodeClassType);
+ assertEquals("NodeClass", nodeClassType.getBrowseName().name());
+ assertTrue(seededTree.isResolved(NodeIds.NodeClass));
+ assertNotNull(nodeClassType.getDataTypeDefinition());
+
+ // ServerState is a seeded enum subtype with an EnumDefinition
+ DataType serverStateType = seededTree.getDataType(NodeIds.ServerState);
+ assertNotNull(serverStateType);
+ assertEquals("ServerState", serverStateType.getBrowseName().name());
+ assertNotNull(serverStateType.getDataTypeDefinition());
+ }
+
+ @Test
+ void structureSubtypesAreSeeded() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Structure and its subtypes are in the seed
+ assertTrue(seededTree.isResolved(NodeIds.Structure));
+ assertTrue(seededTree.isResolved(NodeIds.XVType));
+ assertTrue(seededTree.isResolved(NodeIds.RolePermissionType));
+ assertTrue(seededTree.isResolved(NodeIds.StructureDefinition));
+ }
+
+ @Test
+ void seededStructureSubtypesHaveEncodingIdsAndDefinitions() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // XVType is a seeded structure subtype with encoding IDs and definition
+ DataType xvType = seededTree.getDataType(NodeIds.XVType);
+ assertNotNull(xvType);
+ assertEquals("XVType", xvType.getBrowseName().name());
+ assertTrue(seededTree.isResolved(NodeIds.XVType));
+ assertNotNull(xvType.getBinaryEncodingId());
+ assertNotNull(xvType.getDataTypeDefinition());
+
+ // RolePermissionType is a seeded structure subtype with encoding IDs and definition
+ DataType rolePermType = seededTree.getDataType(NodeIds.RolePermissionType);
+ assertNotNull(rolePermType);
+ assertEquals("RolePermissionType", rolePermType.getBrowseName().name());
+ assertNotNull(rolePermType.getBinaryEncodingId());
+ assertNotNull(rolePermType.getDataTypeDefinition());
+ }
+
+ @Test
+ void seededTreeMatchesEagerTreeForCommonTypes() throws UaException {
+ DataTypeTree eagerTree = DataTypeTreeBuilder.build(client);
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Test types that are in the seed
+ NodeId[] seededTypes = {
+ NodeIds.Int32,
+ NodeIds.String,
+ NodeIds.Double,
+ NodeIds.DateTime,
+ NodeIds.ByteString,
+ NodeIds.Boolean,
+ NodeIds.Guid,
+ NodeIds.Number,
+ NodeIds.Integer,
+ NodeIds.UInteger,
+ NodeIds.Enumeration
+ };
+
+ for (NodeId typeId : seededTypes) {
+ DataType eagerType = eagerTree.getDataType(typeId);
+ DataType seededType = seededTree.getDataType(typeId);
+
+ if (eagerType != null) {
+ assertNotNull(seededType, "Seeded tree should have type: " + typeId);
+ assertEquals(
+ eagerType.getBrowseName(),
+ seededType.getBrowseName(),
+ "BrowseName mismatch for " + typeId);
+ assertEquals(
+ eagerType.isAbstract(), seededType.isAbstract(), "IsAbstract mismatch for " + typeId);
+ }
+ }
+ }
+
+ @Test
+ void getRootContainsAllSeededTypes() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ Tree root = seededTree.getRoot();
+ var count = new AtomicInteger(0);
+ root.traverseNodes(node -> count.incrementAndGet());
+
+ // The seed tree should contain many types (all the primitives, enums, etc.)
+ assertTrue(count.get() > 50, "Seeded tree should contain many pre-loaded types");
+ }
+
+ @Test
+ void clearFailedResolutionsAllowsRetry() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Try to resolve a non-existent type
+ NodeId fakeTypeId = new NodeId(999, "FakeDataType");
+ DataType result = seededTree.getDataType(fakeTypeId);
+
+ // Should return null
+ assertTrue(result == null || !seededTree.isResolved(fakeTypeId));
+
+ // Clear failed resolutions
+ seededTree.clearFailedResolutions();
+
+ // Now it can be attempted again
+ result = seededTree.getDataType(fakeTypeId);
+ assertTrue(result == null || !seededTree.isResolved(fakeTypeId));
+ }
+
+ @Test
+ void containsTypeReturnsTrueForSeededTypes() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // These should return true immediately without triggering resolution
+ assertTrue(seededTree.containsType(NodeIds.Int32));
+ assertTrue(seededTree.containsType(NodeIds.String));
+ assertTrue(seededTree.containsType(NodeIds.Double));
+ assertTrue(seededTree.containsType(NodeIds.Enumeration));
+ assertTrue(seededTree.containsType(NodeIds.Boolean));
+ }
+
+ @Test
+ void getBuiltinTypeWorksForSeededTypes() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Builtin type resolution should work for seeded types
+ assertEquals(OpcUaDataType.Int32, seededTree.getBuiltinType(NodeIds.Int32));
+ assertEquals(OpcUaDataType.String, seededTree.getBuiltinType(NodeIds.String));
+ assertEquals(OpcUaDataType.Double, seededTree.getBuiltinType(NodeIds.Double));
+ assertEquals(OpcUaDataType.Boolean, seededTree.getBuiltinType(NodeIds.Boolean));
+ }
+
+ @Test
+ void isEnumTypeWorksForSeededTypes() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Enumeration subtypes are seeded and isEnumType works immediately
+ assertTrue(seededTree.isEnumType(NodeIds.NodeClass));
+ assertTrue(seededTree.isEnumType(NodeIds.ServerState));
+ assertTrue(seededTree.isEnumType(NodeIds.RedundancySupport));
+
+ // Non-enum types (which are seeded) should not be recognized as enums
+ assertFalse(seededTree.isEnumType(NodeIds.Int32));
+ assertFalse(seededTree.isEnumType(NodeIds.String));
+ }
+
+ @Test
+ void isStructTypeWorksForSeededTypes() {
+ var seededTree =
+ new LazyClientDataTypeTree(client, LazyClientDataTypeTreeSeed.createSeedTree());
+
+ // Structure is in the seed
+ assertTrue(seededTree.isResolved(NodeIds.Structure));
+
+ // Note: isStructType uses isSubtypeOf, so Structure itself is NOT a struct type
+ // (a type is not a subtype of itself)
+ assertFalse(seededTree.isStructType(NodeIds.Structure));
+
+ // Primitive types (which are seeded) are not structs
+ assertFalse(seededTree.isStructType(NodeIds.Int32));
+ assertFalse(seededTree.isStructType(NodeIds.String));
+ assertFalse(seededTree.isStructType(NodeIds.Boolean));
+
+ // Seeded structure subtypes can be verified with isStructType immediately
+ assertTrue(seededTree.isStructType(NodeIds.XVType));
+ assertTrue(seededTree.isStructType(NodeIds.RolePermissionType));
+ }
+}
diff --git a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/OpcUaClient.java b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/OpcUaClient.java
index 7420e3ed3..e61b20ee9 100644
--- a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/OpcUaClient.java
+++ b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/OpcUaClient.java
@@ -38,17 +38,17 @@
import org.eclipse.milo.opcua.sdk.client.session.SessionFsmFactory;
import org.eclipse.milo.opcua.sdk.client.subscriptions.OpcUaSubscription;
import org.eclipse.milo.opcua.sdk.client.subscriptions.PublishingManager;
+import org.eclipse.milo.opcua.sdk.client.typetree.DataTypeManagerFactory;
import org.eclipse.milo.opcua.sdk.client.typetree.DataTypeTreeBuilder;
+import org.eclipse.milo.opcua.sdk.client.typetree.DataTypeTreeFactory;
+import org.eclipse.milo.opcua.sdk.client.typetree.LazyClientDataTypeManager;
import org.eclipse.milo.opcua.sdk.client.typetree.ObjectTypeTreeBuilder;
import org.eclipse.milo.opcua.sdk.client.typetree.VariableTypeTreeBuilder;
-import org.eclipse.milo.opcua.sdk.core.types.codec.DynamicCodecFactory;
-import org.eclipse.milo.opcua.sdk.core.typetree.DataType;
import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
import org.eclipse.milo.opcua.sdk.core.typetree.ObjectTypeTree;
import org.eclipse.milo.opcua.sdk.core.typetree.VariableTypeTree;
import org.eclipse.milo.opcua.stack.core.*;
import org.eclipse.milo.opcua.stack.core.channel.EncodingLimits;
-import org.eclipse.milo.opcua.stack.core.encoding.DataTypeCodec;
import org.eclipse.milo.opcua.stack.core.encoding.DefaultEncodingManager;
import org.eclipse.milo.opcua.stack.core.encoding.EncodingContext;
import org.eclipse.milo.opcua.stack.core.encoding.EncodingManager;
@@ -139,7 +139,6 @@
import org.eclipse.milo.opcua.stack.core.types.structured.SetPublishingModeResponse;
import org.eclipse.milo.opcua.stack.core.types.structured.SetTriggeringRequest;
import org.eclipse.milo.opcua.stack.core.types.structured.SetTriggeringResponse;
-import org.eclipse.milo.opcua.stack.core.types.structured.StructureDefinition;
import org.eclipse.milo.opcua.stack.core.types.structured.SubscriptionAcknowledgement;
import org.eclipse.milo.opcua.stack.core.types.structured.TransferSubscriptionsRequest;
import org.eclipse.milo.opcua.stack.core.types.structured.TransferSubscriptionsResponse;
@@ -158,7 +157,6 @@
import org.eclipse.milo.opcua.stack.core.util.LongSequence;
import org.eclipse.milo.opcua.stack.core.util.ManifestUtil;
import org.eclipse.milo.opcua.stack.core.util.Namespaces;
-import org.eclipse.milo.opcua.stack.core.util.Tree;
import org.eclipse.milo.opcua.stack.core.util.Unit;
import org.eclipse.milo.opcua.stack.transport.client.ClientApplicationContext;
import org.eclipse.milo.opcua.stack.transport.client.OpcClientTransport;
@@ -329,8 +327,9 @@ public static OpcUaClient create(
private final VariableTypeManager variableTypeManager = new VariableTypeManager();
- private DataTypeManagerInitializer dataTypeManagerInitializer =
- new DefaultDataTypeManagerInitializer();
+ private DataTypeTreeFactory dataTypeTreeFactory = DataTypeTreeFactory.eager();
+
+ private DataTypeManagerFactory dynamicDataTypeManagerFactory = DataTypeManagerFactory.eager();
private final EncodingManager encodingManager = DefaultEncodingManager.createAndInitialize();
@@ -642,21 +641,22 @@ public DataTypeManager getStaticDataTypeManager() {
/**
* Get the client's "dynamic" {@link DataTypeManager}.
*
- * This {@link DataTypeManager} is for dynamic codecs that were created by reading datatype
- * information from the server at runtime.
+ *
This {@link DataTypeManager} is for dynamic codecs created by reading datatype information
+ * from the server at runtime.
+ *
+ *
By default, the client uses {@link DataTypeManagerFactory#eager()}, which creates a {@link
+ * DefaultDataTypeManager} with all known types eagerly registered.
+ *
+ *
Use {@link #setDynamicDataTypeManagerFactory(DataTypeManagerFactory)} with {@link
+ * DataTypeManagerFactory#lazy()} to configure the client with a {@link LazyClientDataTypeManager}
+ * that resolves codecs on demand.
*
* @return the client's dynamic {@link DataTypeManager}.
- * @see #setDataTypeManagerInitializer(DataTypeManagerInitializer)
+ * @see #setDynamicDataTypeManagerFactory(DataTypeManagerFactory)
*/
public DataTypeManager getDynamicDataTypeManager() throws UaException {
return dynamicDataTypeManager.getOrThrow(
- () -> {
- DataTypeManager dataTypeManager =
- DefaultDataTypeManager.createAndInitialize(getNamespaceTable());
- dataTypeManagerInitializer.initialize(
- getNamespaceTable(), getDataTypeTree(), dataTypeManager);
- return dataTypeManager;
- });
+ () -> dynamicDataTypeManagerFactory.create(this, getNamespaceTable(), getDataTypeTree()));
}
/**
@@ -886,7 +886,7 @@ private void updateServerTable(String[] serverArray) {
*/
public DataTypeTree getDataTypeTree() throws UaException {
try {
- return dataTypeTree.getOrThrow(() -> DataTypeTreeBuilder.build(this));
+ return dataTypeTree.getOrThrow(() -> dataTypeTreeFactory.create(this));
} catch (Exception e) {
throw new UaException(e);
}
@@ -1079,17 +1079,51 @@ public RequestHeader newRequestHeader(NodeId authToken, UInteger requestTimeout)
}
/**
- * Set the {@link DataTypeManagerInitializer} that called to register codecs with the client's
- * dynamic {@link DataTypeManager}.
+ * Set the {@link DataTypeTreeFactory} used to create the {@link DataTypeTree}.
+ *
+ *
By default, the client uses {@link DataTypeTreeFactory#eager()}, which eagerly builds the
+ * complete DataTypeTree using {@link DataTypeTreeBuilder#build(OpcUaClient)}.
+ *
+ *
Use {@link DataTypeTreeFactory#lazy()} to configure the client with a lazy-loading tree that
+ * resolves types on demand. This can be more efficient when only a subset of types is needed or
+ * when the server doesn't support recursive forward browsing of the DataType hierarchy.
+ *
+ *
This resets the client's cached {@link DataTypeTree}. It will be built or rebuilt the next
+ * time it is accessed.
+ *
+ * @param dataTypeTreeFactory the {@link DataTypeTreeFactory} to set.
+ * @see #getDataTypeTree()
+ * @see DataTypeTreeFactory#eager()
+ * @see DataTypeTreeFactory#lazy()
+ */
+ public void setDataTypeTreeFactory(DataTypeTreeFactory dataTypeTreeFactory) {
+ this.dataTypeTreeFactory = dataTypeTreeFactory;
+
+ dataTypeTree.reset();
+ }
+
+ /**
+ * Set the {@link DataTypeManagerFactory} used to create the dynamic {@link DataTypeManager}.
*
- *
This resets the client's dynamic {@link DataTypeManager} and {@link EncodingContext}. They
- * will be built or rebuilt the next time they are accessed.
+ *
By default, the client uses {@link DataTypeManagerFactory#eager()}, which creates a {@link
+ * DefaultDataTypeManager} with all known types eagerly registered.
*
- * @param dataTypeManagerInitializer the {@link DataTypeManagerInitializer} to set.
+ *
Use {@link DataTypeManagerFactory#lazy()} to configure the client with a {@link
+ * LazyClientDataTypeManager} that resolves codecs on demand. This pairs well with {@link
+ * DataTypeTreeFactory#lazy()} for a fully lazy type resolution system.
+ *
+ *
This resets the client's cached {@link DataTypeManager}. It will be created again the next
+ * time it is accessed.
+ *
+ * @param dynamicDataTypeManagerFactory the {@link DataTypeManagerFactory} to set.
* @see #getDynamicDataTypeManager()
+ * @see DataTypeManagerFactory#eager()
+ * @see DataTypeManagerFactory#lazy()
*/
- public void setDataTypeManagerInitializer(DataTypeManagerInitializer dataTypeManagerInitializer) {
- this.dataTypeManagerInitializer = dataTypeManagerInitializer;
+ public void setDynamicDataTypeManagerFactory(
+ DataTypeManagerFactory dynamicDataTypeManagerFactory) {
+
+ this.dynamicDataTypeManagerFactory = dynamicDataTypeManagerFactory;
dynamicDataTypeManager.reset();
dynamicEncodingContext.reset();
@@ -2987,99 +3021,4 @@ public void removeSessionInitializer(SessionInitializer initializer) {
sessionFsm.removeInitializer(initializer);
logger.debug("Removed SessionInitializer: {}", initializer);
}
-
- public interface DataTypeManagerInitializer {
-
- /**
- * Register codecs for custom data types.
- *
- * @param namespaceTable the Server's {@link NamespaceTable}.
- * @param dataTypeTree the Client's {@link DataTypeTree}.
- * @param dataTypeManager the {@link DataTypeManager} to register codecs with.
- */
- void initialize(
- NamespaceTable namespaceTable, DataTypeTree dataTypeTree, DataTypeManager dataTypeManager)
- throws UaException;
- }
-
- public static class DefaultDataTypeManagerInitializer implements DataTypeManagerInitializer {
-
- private final CodecFactory codecFactory;
-
- /**
- * Create a new {@link DefaultDataTypeManagerInitializer} that uses {@link DynamicCodecFactory}.
- */
- public DefaultDataTypeManagerInitializer() {
- this(DynamicCodecFactory::create);
- }
-
- /**
- * Create a new {@link DefaultDataTypeManagerInitializer} using the provided {@link
- * CodecFactory}.
- *
- * @param codecFactory the {@link CodecFactory} to use when creating {@link DataTypeCodec}s.
- */
- public DefaultDataTypeManagerInitializer(CodecFactory codecFactory) {
- this.codecFactory = codecFactory;
- }
-
- @Override
- public void initialize(
- NamespaceTable namespaceTable, DataTypeTree dataTypeTree, DataTypeManager dataTypeManager) {
-
- Tree structureNode = dataTypeTree.getTreeNode(NodeIds.Structure);
-
- if (structureNode != null) {
- structureNode.traverse(
- dataType -> {
- if (dataType.getDataTypeDefinition() != null) {
- LoggerFactory.getLogger(getClass())
- .debug(
- "Registering type: name={}, dataTypeId={}",
- dataType.getBrowseName(),
- dataType.getNodeId());
-
- String namespaceUri = namespaceTable.get(dataType.getNodeId().getNamespaceIndex());
-
- if (namespaceUri == null) {
- throw new UaRuntimeException(
- StatusCodes.Bad_UnexpectedError,
- "DataType namespace not registered: "
- + dataType.getNodeId().toParseableString());
- }
-
- dataTypeManager.registerType(
- dataType.getNodeId(),
- codecFactory.create(dataType, dataTypeTree),
- getBinaryEncodingId(dataType),
- dataType.getXmlEncodingId(),
- dataType.getJsonEncodingId());
- }
- });
- } else {
- LoggerFactory.getLogger(getClass())
- .warn(
- "Structure (i=22) not found in the DataType tree; is the Server's DataType"
- + " hierarchy sane?");
- }
- }
-
- private static NodeId getBinaryEncodingId(DataType dataType) {
- NodeId binaryEncodingId = dataType.getBinaryEncodingId();
-
- if (binaryEncodingId == null
- && dataType.getDataTypeDefinition() instanceof StructureDefinition definition) {
-
- // Hail mary work around for non-compliant Servers that don't have encoding nodes
- // in their address space. The DefaultEncodingId in a StructureDefinition shall
- // always be the Default Binary encoding, so let's see if the Server at least set
- // this correctly.
- // See https://reference.opcfoundation.org/Core/Part3/v105/docs/8.48
-
- binaryEncodingId = definition.getDefaultEncodingId();
- }
-
- return binaryEncodingId;
- }
- }
}
diff --git a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/ClientBrowseUtils.java b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/ClientBrowseUtils.java
new file mode 100644
index 000000000..74b894155
--- /dev/null
+++ b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/ClientBrowseUtils.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import static java.util.Objects.requireNonNull;
+import static java.util.Objects.requireNonNullElse;
+import static org.eclipse.milo.opcua.stack.core.util.Lists.partition;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.client.OperationLimits;
+import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString;
+import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
+import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
+import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
+import org.eclipse.milo.opcua.stack.core.types.structured.BrowseNextResponse;
+import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;
+import org.eclipse.milo.opcua.stack.core.types.structured.ReadResponse;
+import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;
+import org.eclipse.milo.opcua.stack.core.types.structured.ReferenceDescription;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Shared utility methods for client-side browse and read operations with operation limit handling.
+ */
+final class ClientBrowseUtils {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ClientBrowseUtils.class);
+
+ private ClientBrowseUtils() {}
+
+ /**
+ * Read values with operation limits, partitioning requests as necessary.
+ *
+ * @param client the OPC UA client.
+ * @param readValueIds the list of ReadValueIds to read.
+ * @param limits the operation limits from the server.
+ * @return the list of DataValues corresponding to the read requests.
+ */
+ static List readWithOperationLimits(
+ OpcUaClient client, List readValueIds, OperationLimits limits) {
+
+ if (readValueIds.isEmpty()) {
+ return List.of();
+ }
+
+ LOGGER.debug("readWithOperationLimits: {}", readValueIds.size());
+
+ int partitionSize =
+ limits
+ .maxNodesPerRead()
+ .map(UInteger::intValue)
+ .filter(v -> v > 0)
+ .orElse(Integer.MAX_VALUE);
+
+ var values = new ArrayList();
+
+ partition(readValueIds, partitionSize)
+ .forEach(
+ partitionList -> {
+ try {
+ ReadResponse response = client.read(0.0, TimestampsToReturn.Neither, partitionList);
+ DataValue[] results = response.getResults();
+ Collections.addAll(values, requireNonNull(results));
+ } catch (UaException e) {
+ LOGGER.debug("Read failed: {}", e.getMessage(), e);
+ var value = new DataValue(e.getStatusCode());
+ values.addAll(Collections.nCopies(partitionList.size(), value));
+ }
+ });
+
+ return values;
+ }
+
+ /**
+ * Browse with operation limits, partitioning requests as necessary.
+ *
+ * @param client the OPC UA client.
+ * @param browseDescriptions the list of BrowseDescriptions.
+ * @param limits the operation limits from the server.
+ * @return the list of reference description lists corresponding to each browse request.
+ */
+ static List> browseWithOperationLimits(
+ OpcUaClient client, List browseDescriptions, OperationLimits limits) {
+
+ if (browseDescriptions.isEmpty()) {
+ return List.of();
+ }
+
+ LOGGER.debug("browseWithOperationLimits: {}", browseDescriptions.size());
+
+ int partitionSize =
+ limits
+ .maxNodesPerBrowse()
+ .map(UInteger::intValue)
+ .filter(v -> v > 0)
+ .orElse(Integer.MAX_VALUE);
+
+ var references = new ArrayList>();
+
+ partition(browseDescriptions, partitionSize)
+ .forEach(partitionList -> references.addAll(browse(client, partitionList)));
+
+ return references;
+ }
+
+ /**
+ * Browse a list of nodes and return all reference descriptions, handling continuation points.
+ *
+ * @param client the OPC UA client.
+ * @param browseDescriptions the list of BrowseDescriptions.
+ * @return a list of reference description lists, one per browse description.
+ */
+ static List> browse(
+ OpcUaClient client, List browseDescriptions) {
+
+ if (browseDescriptions.isEmpty()) {
+ return List.of();
+ }
+
+ final var referenceDescriptionLists = new ArrayList>();
+
+ try {
+ client
+ .browse(browseDescriptions)
+ .forEach(
+ result -> {
+ if (result.getStatusCode().isGood()) {
+ var references = new ArrayList();
+
+ ReferenceDescription[] refs =
+ requireNonNullElse(result.getReferences(), new ReferenceDescription[0]);
+ Collections.addAll(references, refs);
+
+ ByteString continuationPoint = result.getContinuationPoint();
+ List nextRefs = maybeBrowseNext(client, continuationPoint);
+ references.addAll(nextRefs);
+
+ referenceDescriptionLists.add(references);
+ } else {
+ referenceDescriptionLists.add(List.of());
+ }
+ });
+ } catch (UaException e) {
+ referenceDescriptionLists.addAll(Collections.nCopies(browseDescriptions.size(), List.of()));
+ }
+
+ return referenceDescriptionLists;
+ }
+
+ /**
+ * Continue browsing using a continuation point until all references are retrieved.
+ *
+ * @param client the OPC UA client.
+ * @param continuationPoint the continuation point from a previous browse.
+ * @return the list of additional reference descriptions.
+ */
+ static List maybeBrowseNext(
+ OpcUaClient client, ByteString continuationPoint) {
+
+ var references = new ArrayList();
+
+ while (continuationPoint != null && continuationPoint.isNotNull()) {
+ try {
+ BrowseNextResponse response = client.browseNext(false, List.of(continuationPoint));
+
+ BrowseResult result = requireNonNull(response.getResults())[0];
+
+ ReferenceDescription[] rds =
+ requireNonNullElse(result.getReferences(), new ReferenceDescription[0]);
+
+ references.addAll(List.of(rds));
+
+ continuationPoint = result.getContinuationPoint();
+ } catch (Exception e) {
+ LOGGER.warn("BrowseNext failed: {}", e.getMessage(), e);
+ return references;
+ }
+ }
+
+ return references;
+ }
+}
diff --git a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeManagerFactory.java b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeManagerFactory.java
new file mode 100644
index 000000000..df9919fcf
--- /dev/null
+++ b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeManagerFactory.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import org.eclipse.milo.opcua.sdk.client.CodecFactory;
+import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.core.types.codec.DynamicCodecFactory;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataType;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
+import org.eclipse.milo.opcua.stack.core.NamespaceTable;
+import org.eclipse.milo.opcua.stack.core.NodeIds;
+import org.eclipse.milo.opcua.stack.core.StatusCodes;
+import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.UaRuntimeException;
+import org.eclipse.milo.opcua.stack.core.types.DataTypeManager;
+import org.eclipse.milo.opcua.stack.core.types.DefaultDataTypeManager;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.structured.StructureDefinition;
+import org.eclipse.milo.opcua.stack.core.util.Tree;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A factory that creates a {@link DataTypeManager} for a given {@link OpcUaClient}.
+ *
+ * Implementations can create different types of DataTypeManagers, such as:
+ *
+ *
+ * - An eagerly initialized manager via {@link DefaultDataTypeManager#createAndInitialize}
+ *
- A lazily-loading manager via {@link LazyClientDataTypeManager}
+ *
+ *
+ * @see DefaultDataTypeManager
+ * @see LazyClientDataTypeManager
+ */
+@FunctionalInterface
+public interface DataTypeManagerFactory {
+
+ /**
+ * Creates a {@link DataTypeManager} for the given client.
+ *
+ * @param client the {@link OpcUaClient} to create a DataTypeManager for.
+ * @param namespaceTable the server's {@link NamespaceTable}.
+ * @param dataTypeTree the {@link DataTypeTree} to use for type resolution.
+ * @return a new {@link DataTypeManager} instance.
+ * @throws UaException if an error occurs while creating the manager.
+ */
+ DataTypeManager create(
+ OpcUaClient client, NamespaceTable namespaceTable, DataTypeTree dataTypeTree)
+ throws UaException;
+
+ /**
+ * Returns the default factory that eagerly initializes a {@link DataTypeManager} using {@link
+ * DefaultDataTypeManager#createAndInitialize(NamespaceTable)}.
+ *
+ * The eager factory creates and initializes all codecs for known structure types in the {@link
+ * DataTypeTree} at creation time, using {@link DynamicCodecFactory} and the default initializer.
+ *
+ * @return the default {@link DataTypeManagerFactory}.
+ */
+ static DataTypeManagerFactory eager() {
+ return eager(new DefaultInitializer());
+ }
+
+ /**
+ * Returns an eager factory that uses a {@link DefaultInitializer} with the provided {@link
+ * CodecFactory}.
+ *
+ *
The eager factory creates and initializes all codecs for known structure types in the {@link
+ * DataTypeTree} at creation time.
+ *
+ * @param codecFactory the {@link CodecFactory} to use when creating codecs.
+ * @return a {@link DataTypeManagerFactory} that eagerly initializes types.
+ */
+ static DataTypeManagerFactory eager(CodecFactory codecFactory) {
+ return eager(new DefaultInitializer(codecFactory));
+ }
+
+ /**
+ * Returns an eager factory that uses the provided {@link Initializer}.
+ *
+ *
The eager factory creates and initializes all codecs for known structure types in the {@link
+ * DataTypeTree} at creation time.
+ *
+ * @param initializer the {@link Initializer} to use for registering codecs.
+ * @return a {@link DataTypeManagerFactory} that eagerly initializes types.
+ */
+ static DataTypeManagerFactory eager(Initializer initializer) {
+ return (client, namespaceTable, dataTypeTree) -> {
+ DataTypeManager dataTypeManager = DefaultDataTypeManager.createAndInitialize(namespaceTable);
+ initializer.initialize(namespaceTable, dataTypeTree, dataTypeManager);
+ return dataTypeManager;
+ };
+ }
+
+ /**
+ * Returns a factory that creates a {@link LazyClientDataTypeManager}.
+ *
+ *
The lazy factory creates a manager that resolves codecs on demand when they are first
+ * requested, rather than eagerly registering all codecs at creation time. Uses {@link
+ * DynamicCodecFactory} by default.
+ *
+ * @return a {@link DataTypeManagerFactory} that creates lazy-loading managers.
+ */
+ static DataTypeManagerFactory lazy() {
+ return lazy(DynamicCodecFactory::create);
+ }
+
+ /**
+ * Returns a factory that creates a {@link LazyClientDataTypeManager} with a custom {@link
+ * CodecFactory}.
+ *
+ *
The lazy factory creates a manager that resolves codecs on demand when they are first
+ * requested, rather than eagerly registering all codecs at creation time.
+ *
+ * @param codecFactory the {@link CodecFactory} to use when creating codecs on demand.
+ * @return a {@link DataTypeManagerFactory} that creates lazy-loading managers.
+ */
+ static DataTypeManagerFactory lazy(CodecFactory codecFactory) {
+ return (client, namespaceTable, dataTypeTree) ->
+ new LazyClientDataTypeManager(client, namespaceTable, dataTypeTree, codecFactory::create);
+ }
+
+ /**
+ * An initializer that registers codecs for custom data types with a {@link DataTypeManager}.
+ *
+ *
Implementations traverse the {@link DataTypeTree} and register codecs for structure types.
+ */
+ interface Initializer {
+
+ /**
+ * Register codecs for custom data types.
+ *
+ * @param namespaceTable the Server's {@link NamespaceTable}.
+ * @param dataTypeTree the Client's {@link DataTypeTree}.
+ * @param dataTypeManager the {@link DataTypeManager} to register codecs with.
+ * @throws UaException if an error occurs during initialization.
+ */
+ void initialize(
+ NamespaceTable namespaceTable, DataTypeTree dataTypeTree, DataTypeManager dataTypeManager)
+ throws UaException;
+ }
+
+ /**
+ * The default {@link Initializer} implementation that traverses the DataType hierarchy and
+ * registers codecs for all structure types with a {@link DataTypeManager}.
+ *
+ *
Uses {@link DynamicCodecFactory} by default, but can be configured with a custom {@link
+ * CodecFactory}.
+ */
+ class DefaultInitializer implements Initializer {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultInitializer.class);
+
+ private final CodecFactory codecFactory;
+
+ /** Create a new {@link DefaultInitializer} that uses {@link DynamicCodecFactory}. */
+ public DefaultInitializer() {
+ this(DynamicCodecFactory::create);
+ }
+
+ /**
+ * Create a new {@link DefaultInitializer} using the provided {@link CodecFactory}.
+ *
+ * @param codecFactory the {@link CodecFactory} to use when creating codecs.
+ */
+ public DefaultInitializer(CodecFactory codecFactory) {
+ this.codecFactory = codecFactory;
+ }
+
+ @Override
+ public void initialize(
+ NamespaceTable namespaceTable, DataTypeTree dataTypeTree, DataTypeManager dataTypeManager) {
+
+ Tree structureNode = dataTypeTree.getTreeNode(NodeIds.Structure);
+
+ if (structureNode != null) {
+ structureNode.traverse(
+ dataType -> {
+ if (dataType.getDataTypeDefinition() != null) {
+ LOGGER.debug(
+ "Registering type: name={}, dataTypeId={}",
+ dataType.getBrowseName(),
+ dataType.getNodeId());
+
+ String namespaceUri = namespaceTable.get(dataType.getNodeId().getNamespaceIndex());
+
+ if (namespaceUri == null) {
+ throw new UaRuntimeException(
+ StatusCodes.Bad_UnexpectedError,
+ "DataType namespace not registered: "
+ + dataType.getNodeId().toParseableString());
+ }
+
+ dataTypeManager.registerType(
+ dataType.getNodeId(),
+ codecFactory.create(dataType, dataTypeTree),
+ getBinaryEncodingId(dataType),
+ dataType.getXmlEncodingId(),
+ dataType.getJsonEncodingId());
+ }
+ });
+ } else {
+ LOGGER.warn(
+ "Structure (i=22) not found in the DataType tree; is the Server's DataType"
+ + " hierarchy sane?");
+ }
+ }
+
+ private static NodeId getBinaryEncodingId(DataType dataType) {
+ NodeId binaryEncodingId = dataType.getBinaryEncodingId();
+
+ if (binaryEncodingId == null
+ && dataType.getDataTypeDefinition() instanceof StructureDefinition definition) {
+
+ // Hail mary work around for non-compliant Servers that don't have encoding nodes
+ // in their address space. The DefaultEncodingId in a StructureDefinition shall
+ // always be the Default Binary encoding, so let's see if the Server at least set
+ // this correctly.
+ // See https://reference.opcfoundation.org/Core/Part3/v105/docs/8.48
+
+ binaryEncodingId = definition.getDefaultEncodingId();
+ }
+
+ return binaryEncodingId;
+ }
+ }
+}
diff --git a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeBuilder.java b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeBuilder.java
index bf7ccd157..f5385a3a2 100644
--- a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeBuilder.java
+++ b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeBuilder.java
@@ -10,19 +10,16 @@
package org.eclipse.milo.opcua.sdk.client.typetree;
-import static java.util.Objects.requireNonNull;
-import static java.util.Objects.requireNonNullElse;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
-import static org.eclipse.milo.opcua.stack.core.util.Lists.partition;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.stream.Collectors;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.client.OperationLimits;
import org.eclipse.milo.opcua.sdk.core.typetree.DataType;
import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
import org.eclipse.milo.opcua.stack.core.AttributeId;
@@ -30,13 +27,17 @@
import org.eclipse.milo.opcua.stack.core.NodeIds;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.types.DataTypeEncoding;
-import org.eclipse.milo.opcua.stack.core.types.builtin.*;
-import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
+import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
+import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseDirection;
import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseResultMask;
import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
-import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
-import org.eclipse.milo.opcua.stack.core.types.structured.*;
+import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
+import org.eclipse.milo.opcua.stack.core.types.structured.DataTypeDefinition;
+import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;
+import org.eclipse.milo.opcua.stack.core.types.structured.ReferenceDescription;
import org.eclipse.milo.opcua.stack.core.util.Tree;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
@@ -72,11 +73,9 @@ public static DataTypeTree build(OpcUaClient client) throws UaException {
NamespaceTable namespaceTable = client.readNamespaceTable();
- UInteger[] operationLimits = readOperationLimits(client);
- UInteger maxNodesPerBrowse = operationLimits[0];
- UInteger maxNodesPerRead = operationLimits[1];
+ OperationLimits operationLimits = client.getOperationLimits();
- addChildren(List.of(root), client, namespaceTable, maxNodesPerBrowse, maxNodesPerRead);
+ addChildren(List.of(root), client, namespaceTable, operationLimits);
return new DataTypeTree(root);
}
@@ -105,11 +104,10 @@ private static void addChildren(
List> parentTypes,
OpcUaClient client,
NamespaceTable namespaceTable,
- UInteger maxNodesPerBrowse,
- UInteger maxNodesPerRead) {
+ OperationLimits operationLimits) {
List> parentSubtypes =
- browseWithOperationLimits(
+ ClientBrowseUtils.browseWithOperationLimits(
client,
parentTypes.stream()
.map(
@@ -122,7 +120,7 @@ private static void addChildren(
uint(NodeClass.DataType.getValue()),
uint(BrowseResultMask.All.getValue())))
.collect(Collectors.toList()),
- maxNodesPerBrowse);
+ operationLimits);
var childTypes = new ArrayList>();
@@ -138,10 +136,10 @@ private static void addChildren(
.collect(Collectors.toList());
List> encodingReferences =
- browseEncodings(client, dataTypeIds, maxNodesPerBrowse);
+ browseEncodings(client, dataTypeIds, operationLimits);
List dataTypeAttributes =
- readDataTypeAttributes(client, dataTypeIds, maxNodesPerRead);
+ readDataTypeAttributes(client, dataTypeIds, operationLimits);
assert subtypes.size() == dataTypeIds.size()
&& subtypes.size() == encodingReferences.size()
@@ -202,75 +200,12 @@ private static void addChildren(
}
if (!childTypes.isEmpty()) {
- addChildren(childTypes, client, namespaceTable, maxNodesPerBrowse, maxNodesPerRead);
+ addChildren(childTypes, client, namespaceTable, operationLimits);
}
}
- private static List> browse(
- OpcUaClient client, List browseDescriptions) {
-
- if (browseDescriptions.isEmpty()) {
- return List.of();
- }
-
- final var referenceDescriptionLists = new ArrayList>();
-
- try {
- client
- .browse(browseDescriptions)
- .forEach(
- result -> {
- if (result.getStatusCode().isGood()) {
- var references = new ArrayList();
-
- ReferenceDescription[] refs =
- requireNonNullElse(result.getReferences(), new ReferenceDescription[0]);
- Collections.addAll(references, refs);
-
- ByteString continuationPoint = result.getContinuationPoint();
- List nextRefs = maybeBrowseNext(client, continuationPoint);
- references.addAll(nextRefs);
-
- referenceDescriptionLists.add(references);
- } else {
- referenceDescriptionLists.add(List.of());
- }
- });
- } catch (UaException e) {
- referenceDescriptionLists.addAll(Collections.nCopies(browseDescriptions.size(), List.of()));
- }
-
- return referenceDescriptionLists;
- }
-
- private static List maybeBrowseNext(
- OpcUaClient client, ByteString continuationPoint) {
-
- var references = new ArrayList();
-
- while (continuationPoint != null && continuationPoint.isNotNull()) {
- try {
- BrowseNextResponse response = client.browseNext(false, List.of(continuationPoint));
-
- BrowseResult result = requireNonNull(response.getResults())[0];
-
- ReferenceDescription[] rds =
- requireNonNullElse(result.getReferences(), new ReferenceDescription[0]);
-
- references.addAll(List.of(rds));
-
- continuationPoint = result.getContinuationPoint();
- } catch (Exception e) {
- LOGGER.warn("BrowseNext failed: {}", e.getMessage(), e);
- return references;
- }
- }
-
- return references;
- }
-
private static List> browseEncodings(
- OpcUaClient client, List dataTypeIds, UInteger maxNodesPerBrowse) {
+ OpcUaClient client, List dataTypeIds, OperationLimits operationLimits) {
List browseDescriptions =
dataTypeIds.stream()
@@ -285,11 +220,11 @@ private static List> browseEncodings(
uint(BrowseResultMask.All.getValue())))
.collect(Collectors.toList());
- return browseWithOperationLimits(client, browseDescriptions, maxNodesPerBrowse);
+ return ClientBrowseUtils.browseWithOperationLimits(client, browseDescriptions, operationLimits);
}
private static List<@Nullable Attributes> readDataTypeAttributes(
- OpcUaClient client, List dataTypeIds, UInteger maxNodesPerRead) {
+ OpcUaClient client, List dataTypeIds, OperationLimits operationLimits) {
if (dataTypeIds.isEmpty()) {
return List.of();
@@ -308,7 +243,8 @@ private static List> browseEncodings(
var attributes = new ArrayList();
- List values = readWithOperationLimits(client, readValueIds, maxNodesPerRead);
+ List values =
+ ClientBrowseUtils.readWithOperationLimits(client, readValueIds, operationLimits);
for (int i = 0; i < values.size(); i += 2) {
DataValue isAbstractValue = values.get(i);
@@ -349,96 +285,4 @@ private Attributes(Boolean isAbstract, DataTypeDefinition definition) {
this.definition = definition;
}
}
-
- private static UInteger[] readOperationLimits(OpcUaClient client) throws UaException {
- UInteger[] operationLimits = new UInteger[2];
- operationLimits[0] = uint(10);
- operationLimits[1] = uint(100);
-
- List dataValues =
- client.readValues(
- 0.0,
- TimestampsToReturn.Neither,
- List.of(
- NodeIds.OperationLimitsType_MaxNodesPerBrowse,
- NodeIds.OperationLimitsType_MaxNodesPerRead));
-
- DataValue maxNodesPerBrowse = dataValues.get(0);
- if (maxNodesPerBrowse.statusCode().isGood()
- && maxNodesPerBrowse.value().value() instanceof UInteger) {
-
- operationLimits[0] = (UInteger) maxNodesPerBrowse.value().value();
- }
-
- DataValue maxNodesPerRead = dataValues.get(1);
- if (maxNodesPerRead.statusCode().isGood()
- && dataValues.get(1).value().value() instanceof UInteger) {
-
- operationLimits[1] = (UInteger) maxNodesPerRead.value().value();
- }
-
- return operationLimits;
- }
-
- private static List readWithOperationLimits(
- OpcUaClient client, List readValueIds, UInteger maxNodesPerRead) {
-
- if (readValueIds.isEmpty()) {
- return List.of();
- }
-
- LOGGER.debug("readWithOperationLimits: {}", readValueIds.size());
-
- int partitionSize =
- maxNodesPerRead.longValue() > Integer.MAX_VALUE
- ? Integer.MAX_VALUE
- : maxNodesPerRead.intValue();
-
- if (partitionSize == 0) {
- partitionSize = Integer.MAX_VALUE;
- }
-
- var values = new ArrayList();
-
- partition(readValueIds, partitionSize)
- .forEach(
- partition -> {
- try {
- ReadResponse response = client.read(0.0, TimestampsToReturn.Neither, partition);
- DataValue[] results = response.getResults();
- Collections.addAll(values, requireNonNull(results));
- } catch (UaException e) {
- var value = new DataValue(e.getStatusCode());
- values.addAll(Collections.nCopies(partition.size(), value));
- }
- });
-
- return values;
- }
-
- private static List> browseWithOperationLimits(
- OpcUaClient client, List browseDescriptions, UInteger maxNodesPerBrowse) {
-
- if (browseDescriptions.isEmpty()) {
- return List.of();
- }
-
- LOGGER.debug("browseWithOperationLimits: {}", browseDescriptions.size());
-
- int partitionSize =
- maxNodesPerBrowse.longValue() > Integer.MAX_VALUE
- ? Integer.MAX_VALUE
- : maxNodesPerBrowse.intValue();
-
- if (partitionSize == 0) {
- partitionSize = Integer.MAX_VALUE;
- }
-
- var references = new ArrayList>();
-
- partition(browseDescriptions, partitionSize)
- .forEach(partition -> references.addAll(browse(client, partition)));
-
- return references;
- }
}
diff --git a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeFactory.java b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeFactory.java
new file mode 100644
index 000000000..b89e0bd1c
--- /dev/null
+++ b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/DataTypeTreeFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
+import org.eclipse.milo.opcua.stack.core.UaException;
+
+/**
+ * A factory that creates a {@link DataTypeTree} for a given {@link OpcUaClient}.
+ *
+ * Implementations can create different types of DataTypeTrees, such as:
+ *
+ *
+ * - An eagerly built tree via {@link DataTypeTreeBuilder#build(OpcUaClient)}
+ *
- A lazily-loaded tree via {@link LazyClientDataTypeTree}
+ *
+ *
+ * @see DataTypeTreeBuilder
+ * @see LazyClientDataTypeTree
+ */
+@FunctionalInterface
+public interface DataTypeTreeFactory {
+
+ /**
+ * Creates a {@link DataTypeTree} for the given client.
+ *
+ * @param client the {@link OpcUaClient} to create a DataTypeTree for.
+ * @return a new {@link DataTypeTree} instance.
+ * @throws UaException if an error occurs while creating the tree.
+ */
+ DataTypeTree create(OpcUaClient client) throws UaException;
+
+ /**
+ * Returns the default factory that eagerly builds a {@link DataTypeTree} using {@link
+ * DataTypeTreeBuilder#build(OpcUaClient)}.
+ *
+ * @return the default {@link DataTypeTreeFactory}.
+ */
+ static DataTypeTreeFactory eager() {
+ return DataTypeTreeBuilder::build;
+ }
+
+ /**
+ * Returns a factory that creates a {@link LazyClientDataTypeTree}.
+ *
+ * @return a {@link DataTypeTreeFactory} that creates lazy-loading trees.
+ */
+ static DataTypeTreeFactory lazy() {
+ return LazyClientDataTypeTree::new;
+ }
+}
diff --git a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeManager.java b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeManager.java
new file mode 100644
index 000000000..e8a863e2a
--- /dev/null
+++ b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeManager.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.BiFunction;
+import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.core.types.codec.DynamicCodecFactory;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataType;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
+import org.eclipse.milo.opcua.stack.core.NamespaceTable;
+import org.eclipse.milo.opcua.stack.core.NodeIds;
+import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.encoding.DataTypeCodec;
+import org.eclipse.milo.opcua.stack.core.types.DataTypeInitializer;
+import org.eclipse.milo.opcua.stack.core.types.DefaultDataTypeManager;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseDirection;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseResultMask;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
+import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
+import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;
+import org.eclipse.milo.opcua.stack.core.types.structured.StructureDefinition;
+import org.jspecify.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A lazy-loading {@link org.eclipse.milo.opcua.stack.core.types.DataTypeManager} that resolves
+ * codecs on demand.
+ *
+ * This implementation works in conjunction with {@link LazyClientDataTypeTree} to provide fully
+ * lazy resolution of both type information and codecs. When a codec is requested for a type that
+ * isn't already registered, this manager:
+ *
+ *
+ * - Uses the {@link DataTypeTree} to resolve the type (which triggers lazy browsing if using
+ * {@link LazyClientDataTypeTree})
+ *
- Creates a codec using {@link DynamicCodecFactory}
+ *
- Registers the codec for future use
+ *
+ *
+ * Namespace 0 Types
+ *
+ * Built-in types from namespace 0 are pre-initialized via {@link DataTypeInitializer} in the
+ * constructor. Lazy resolution is only triggered for non-namespace-0 types.
+ *
+ *
Thread Safety
+ *
+ * This implementation is thread-safe. All read operations first check the parent class under no
+ * lock, then acquire a write lock only when resolution is needed. Resolution attempts are tracked
+ * to avoid repeated failures.
+ *
+ *
Resolution Behavior
+ *
+ * Resolution errors (e.g., network failures, non-existent types) do not cause exceptions.
+ * Instead, {@code null} is returned. Once a resolution attempt has failed, it will not be retried
+ * unless {@link #clearFailedResolutions()} is called.
+ */
+public class LazyClientDataTypeManager extends DefaultDataTypeManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LazyClientDataTypeManager.class);
+
+ private final OpcUaClient client;
+ private final DataTypeTree dataTypeTree;
+ private final BiFunction codecFactory;
+ private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ private final Set attemptedResolution = ConcurrentHashMap.newKeySet();
+
+ /**
+ * Create a new {@link LazyClientDataTypeManager}.
+ *
+ * @param client a connected {@link OpcUaClient}.
+ * @param namespaceTable the server's {@link NamespaceTable}.
+ * @param dataTypeTree the {@link DataTypeTree} to use for type resolution. This is typically a
+ * {@link LazyClientDataTypeTree} for full lazy behavior.
+ */
+ public LazyClientDataTypeManager(
+ OpcUaClient client, NamespaceTable namespaceTable, DataTypeTree dataTypeTree) {
+
+ this(client, namespaceTable, dataTypeTree, DynamicCodecFactory::create);
+ }
+
+ /**
+ * Create a new {@link LazyClientDataTypeManager} with a custom codec factory.
+ *
+ * @param client a connected {@link OpcUaClient}.
+ * @param namespaceTable the server's {@link NamespaceTable}.
+ * @param dataTypeTree the {@link DataTypeTree} to use for type resolution.
+ * @param codecFactory a factory function that creates {@link DataTypeCodec}s from {@link
+ * DataType} and {@link DataTypeTree}.
+ */
+ public LazyClientDataTypeManager(
+ OpcUaClient client,
+ NamespaceTable namespaceTable,
+ DataTypeTree dataTypeTree,
+ BiFunction codecFactory) {
+
+ this.client = client;
+ this.dataTypeTree = dataTypeTree;
+ this.codecFactory = codecFactory;
+
+ // Pre-initialize namespace 0 codecs
+ new DataTypeInitializer().initialize(namespaceTable, this);
+ }
+
+ /**
+ * Clear failed resolution attempts, allowing retry.
+ *
+ * When a codec 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.
+ */
+ public void clearFailedResolutions() {
+ lock.writeLock().lock();
+ try {
+ attemptedResolution.clear();
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable DataTypeCodec getCodec(NodeId id) {
+ // Fast path: check if already registered
+ DataTypeCodec codec = super.getCodec(id);
+ if (codec != null) {
+ return codec;
+ }
+
+ // Never lazily resolve namespace 0 types; they should already be initialized
+ if (id.getNamespaceIndex().intValue() == 0) {
+ return null;
+ }
+
+ // Skip if we've already tried and failed
+ if (attemptedResolution.contains(id)) {
+ return null;
+ }
+
+ // Slow path: attempt lazy resolution under write lock
+ lock.writeLock().lock();
+ try {
+ // Re-check in case another thread just resolved it
+ codec = super.getCodec(id);
+ if (codec != null) {
+ return codec;
+ }
+
+ // Mark as attempted before trying resolution
+ if (!attemptedResolution.add(id)) {
+ return null;
+ }
+
+ return resolveAndRegisterCodec(id);
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable NodeId getBinaryEncodingId(NodeId dataTypeId) {
+ ensureRegisteredForDataType(dataTypeId);
+ return super.getBinaryEncodingId(dataTypeId);
+ }
+
+ @Override
+ public @Nullable NodeId getXmlEncodingId(NodeId dataTypeId) {
+ ensureRegisteredForDataType(dataTypeId);
+ return super.getXmlEncodingId(dataTypeId);
+ }
+
+ @Override
+ public @Nullable NodeId getJsonEncodingId(NodeId dataTypeId) {
+ ensureRegisteredForDataType(dataTypeId);
+ return super.getJsonEncodingId(dataTypeId);
+ }
+
+ private void ensureRegisteredForDataType(NodeId dataTypeId) {
+ // Skip namespace 0 types
+ if (dataTypeId.getNamespaceIndex().intValue() == 0) {
+ return;
+ }
+
+ // Fast path: already registered
+ if (super.getBinaryEncodingId(dataTypeId) != null
+ || super.getXmlEncodingId(dataTypeId) != null
+ || super.getJsonEncodingId(dataTypeId) != null) {
+ return;
+ }
+
+ // Skip if already attempted
+ if (attemptedResolution.contains(dataTypeId)) {
+ return;
+ }
+
+ // Slow path: attempt resolution under write lock
+ lock.writeLock().lock();
+ try {
+ // Re-check after acquiring lock
+ if (attemptedResolution.contains(dataTypeId)) {
+ return;
+ }
+
+ attemptedResolution.add(dataTypeId);
+ resolveAndRegisterCodecFromDataTypeId(dataTypeId);
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ private @Nullable DataTypeCodec resolveAndRegisterCodec(NodeId id) {
+ try {
+ // First, try to treat `id` as a DataType NodeId
+ DataType dataType = dataTypeTree.getDataType(id);
+
+ if (dataType == null || dataType.getDataTypeDefinition() == null) {
+ // Otherwise, treat `id` as an encoding NodeId and discover its DataType
+ NodeId dataTypeId = browseDataTypeIdForEncoding(id);
+ if (dataTypeId == null) {
+ LOGGER.debug("No DataType found for encoding {}", id);
+ return null;
+ }
+
+ dataType = dataTypeTree.getDataType(dataTypeId);
+ }
+
+ if (dataType == null || dataType.getDataTypeDefinition() == null) {
+ LOGGER.debug("No DataTypeDefinition available for {}", id);
+ return null;
+ }
+
+ // Create the codec and register it
+ return createAndRegisterCodec(dataType);
+ } catch (Exception e) {
+ LOGGER.debug("Error resolving codec for {}: {}", id, e.getMessage());
+ return null;
+ }
+ }
+
+ private void resolveAndRegisterCodecFromDataTypeId(NodeId dataTypeId) {
+ try {
+ DataType dataType = dataTypeTree.getDataType(dataTypeId);
+
+ if (dataType != null && dataType.getDataTypeDefinition() != null) {
+ createAndRegisterCodec(dataType);
+ }
+ } catch (Exception e) {
+ LOGGER.debug("Error resolving codec for DataType {}: {}", dataTypeId, e.getMessage());
+ }
+ }
+
+ private @Nullable DataTypeCodec createAndRegisterCodec(DataType dataType) {
+ NodeId binaryEncodingId = getBinaryEncodingIdFromDataType(dataType);
+
+ DataTypeCodec codec = codecFactory.apply(dataType, dataTypeTree);
+
+ super.registerType(
+ dataType.getNodeId(),
+ codec,
+ binaryEncodingId,
+ dataType.getXmlEncodingId(),
+ dataType.getJsonEncodingId());
+
+ LOGGER.debug(
+ "Lazily registered codec for: name={}, dataTypeId={}",
+ dataType.getBrowseName(),
+ dataType.getNodeId());
+
+ return codec;
+ }
+
+ private static @Nullable NodeId getBinaryEncodingIdFromDataType(DataType dataType) {
+ NodeId binaryEncodingId = dataType.getBinaryEncodingId();
+
+ if (binaryEncodingId == null
+ && dataType.getDataTypeDefinition() instanceof StructureDefinition definition) {
+
+ // Workaround for non-compliant servers that don't have encoding nodes.
+ // The DefaultEncodingId in a StructureDefinition shall always be the Default Binary
+ // encoding.
+ // See https://reference.opcfoundation.org/Core/Part3/v105/docs/8.48
+ binaryEncodingId = definition.getDefaultEncodingId();
+ }
+
+ return binaryEncodingId;
+ }
+
+ private @Nullable NodeId browseDataTypeIdForEncoding(NodeId encodingId) {
+ try {
+ BrowseDescription bd =
+ new BrowseDescription(
+ encodingId,
+ BrowseDirection.Inverse,
+ NodeIds.HasEncoding,
+ false,
+ uint(NodeClass.DataType.getValue()),
+ uint(BrowseResultMask.All.getValue()));
+
+ BrowseResult result = client.browse(bd);
+
+ if (result.getStatusCode().isGood()
+ && result.getReferences() != null
+ && result.getReferences().length > 0) {
+
+ return result
+ .getReferences()[0]
+ .getNodeId()
+ .toNodeId(client.getNamespaceTable())
+ .orElse(null);
+ }
+
+ LOGGER.debug("No DataType found via inverse HasEncoding for encoding {}", encodingId);
+ } catch (UaException e) {
+ LOGGER.debug("Failed to browse DataType for encoding {}: {}", encodingId, e.getMessage());
+ }
+
+ return null;
+ }
+}
diff --git a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTree.java b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTree.java
new file mode 100644
index 000000000..c66b4b97e
--- /dev/null
+++ b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTree.java
@@ -0,0 +1,628 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.sdk.client.OperationLimits;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataType;
+import org.eclipse.milo.opcua.sdk.core.typetree.DataTypeTree;
+import org.eclipse.milo.opcua.stack.core.AttributeId;
+import org.eclipse.milo.opcua.stack.core.NamespaceTable;
+import org.eclipse.milo.opcua.stack.core.NodeIds;
+import org.eclipse.milo.opcua.stack.core.OpcUaDataType;
+import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.types.DataTypeEncoding;
+import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
+import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseDirection;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseResultMask;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
+import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
+import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;
+import org.eclipse.milo.opcua.stack.core.types.structured.DataTypeDefinition;
+import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;
+import org.eclipse.milo.opcua.stack.core.types.structured.ReferenceDescription;
+import org.eclipse.milo.opcua.stack.core.util.Tree;
+import org.jspecify.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A lazy-loading {@link DataTypeTree} that resolves types on demand by browsing inverse HasSubtype
+ * references.
+ *
+ *
Unlike {@link DataTypeTreeBuilder} which eagerly builds the entire tree by forward browsing
+ * from {@link NodeIds#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 {@link #getDataType(NodeId)}. Instead, {@code null} is returned.
+ * Once a resolution attempt has failed, it will not be retried unless {@link
+ * #clearFailedResolutions()} is called.
+ *
+ *
Namespace Table
+ *
+ * This tree caches a copy of the server's {@link NamespaceTable} for converting {@link
+ * org.eclipse.milo.opcua.stack.core.types.builtin.ExpandedNodeId}s during browse operations. If the
+ * server's namespace array changes (e.g., after a reconnection or dynamic namespace registration),
+ * call {@link #invalidateNamespaceTable()} or {@link #refreshNamespaceTable()} to update the cached
+ * copy.
+ */
+public class LazyClientDataTypeTree extends DataTypeTree {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LazyClientDataTypeTree.class);
+
+ private final OpcUaClient client;
+ private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ private final Set attemptedResolution = ConcurrentHashMap.newKeySet();
+
+ private volatile NamespaceTable namespaceTable;
+
+ /**
+ * Create a new {@link LazyClientDataTypeTree} with only {@link NodeIds#BaseDataType} initially
+ * loaded.
+ *
+ * @param client a connected {@link OpcUaClient}.
+ */
+ public LazyClientDataTypeTree(OpcUaClient client) {
+ this(client, createRootTree());
+ }
+
+ /**
+ * Create a new {@link LazyClientDataTypeTree} with 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.
+ *
+ * @param client a connected {@link OpcUaClient}.
+ * @param preSeededTree a pre-built tree containing known types.
+ */
+ public LazyClientDataTypeTree(OpcUaClient client, Tree preSeededTree) {
+ super(preSeededTree);
+ this.client = client;
+ }
+
+ private static Tree createRootTree() {
+ return new Tree<>(
+ null,
+ new ClientDataType(
+ QualifiedName.parse("0:BaseDataType"),
+ NodeIds.BaseDataType,
+ null,
+ null,
+ null,
+ null,
+ true));
+ }
+
+ // ===== Namespace Table Management =====
+
+ private NamespaceTable getNamespaceTable() throws UaException {
+ NamespaceTable ns = namespaceTable;
+ if (ns == null) {
+ synchronized (this) {
+ ns = namespaceTable;
+ if (ns == null) {
+ ns = client.readNamespaceTable();
+ namespaceTable = ns;
+ }
+ }
+ }
+ return ns;
+ }
+
+ /**
+ * Invalidate the cached {@link NamespaceTable}, 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 #refreshNamespaceTable()
+ */
+ public void invalidateNamespaceTable() {
+ namespaceTable = null;
+ }
+
+ /**
+ * Refresh the cached {@link NamespaceTable} immediately by reading it from the server.
+ *
+ *
Unlike {@link #invalidateNamespaceTable()}, this method reads the namespace table
+ * immediately rather than deferring until the next type resolution.
+ *
+ * @throws UaException if reading the namespace table fails.
+ * @see #invalidateNamespaceTable()
+ */
+ public void refreshNamespaceTable() throws UaException {
+ namespaceTable = client.readNamespaceTable();
+ }
+
+ // ===== Resolution State =====
+
+ /**
+ * Check if a type has been resolved/loaded without triggering resolution.
+ *
+ * @param typeId the {@link NodeId} to check.
+ * @return {@code true} if the type is already loaded in the tree.
+ */
+ public boolean isResolved(NodeId typeId) {
+ lock.readLock().lock();
+ try {
+ return types.containsKey(typeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ /**
+ * 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.
+ */
+ public void clearFailedResolutions() {
+ lock.writeLock().lock();
+ try {
+ attemptedResolution.retainAll(types.keySet());
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ // ===== Core Resolution Logic =====
+
+ private void ensureResolved(NodeId dataTypeId) {
+ // Fast path under read lock
+ lock.readLock().lock();
+ try {
+ if (types.containsKey(dataTypeId) || attemptedResolution.contains(dataTypeId)) {
+ return;
+ }
+ } finally {
+ lock.readLock().unlock();
+ }
+
+ // Slow path under write lock
+ lock.writeLock().lock();
+ try {
+ // Re-check under write lock
+ if (types.containsKey(dataTypeId) || attemptedResolution.contains(dataTypeId)) {
+ return;
+ }
+
+ attemptedResolution.add(dataTypeId);
+
+ try {
+ resolvePath(dataTypeId);
+ } catch (UaException e) {
+ LOGGER.debug("Failed to resolve DataType {}: {}", dataTypeId, e.getMessage());
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ private void resolvePath(NodeId dataTypeId) throws UaException {
+ NamespaceTable nsTable = getNamespaceTable();
+ OperationLimits limits = client.getOperationLimits();
+
+ List pathToResolve = browseInverseUntilKnown(dataTypeId, types.keySet(), nsTable);
+
+ if (pathToResolve.isEmpty() || pathToResolve.size() < 2) {
+ LOGGER.debug("Could not resolve path to known ancestor for DataType {}", dataTypeId);
+ return;
+ }
+
+ // pathToResolve = [target, parent, ..., knownAncestor]
+ List nodesToAdd = pathToResolve.subList(0, pathToResolve.size() - 1);
+ NodeId knownAncestorId = pathToResolve.get(pathToResolve.size() - 1);
+
+ List dataTypes = fetchDataTypeInfoBatch(nodesToAdd, nsTable, limits);
+
+ // Add from ancestor toward target (reverse order)
+ Tree parentTree = types.get(knownAncestorId);
+
+ for (int i = nodesToAdd.size() - 1; i >= 0; i--) {
+ ClientDataType dataType = dataTypes.get(i);
+
+ if (dataType != null && parentTree != null) {
+ Tree childTree = parentTree.addChild(dataType);
+ types.put(dataType.getNodeId(), childTree);
+ parentTree = childTree;
+
+ LOGGER.debug("Resolved DataType: {}", dataType.getBrowseName().toParseableString());
+ }
+ }
+ }
+
+ private List fetchDataTypeInfoBatch(
+ List nodeIds, NamespaceTable nsTable, OperationLimits limits) {
+
+ // Read attributes: BrowseName, IsAbstract, DataTypeDefinition
+ var readValueIds = new ArrayList();
+ for (NodeId nodeId : nodeIds) {
+ readValueIds.add(
+ new ReadValueId(nodeId, AttributeId.BrowseName.uid(), null, QualifiedName.NULL_VALUE));
+ readValueIds.add(
+ new ReadValueId(nodeId, AttributeId.IsAbstract.uid(), null, QualifiedName.NULL_VALUE));
+ readValueIds.add(
+ new ReadValueId(
+ nodeId, AttributeId.DataTypeDefinition.uid(), null, QualifiedName.NULL_VALUE));
+ }
+
+ List values =
+ ClientBrowseUtils.readWithOperationLimits(client, readValueIds, limits);
+
+ // Browse encodings
+ List> encodingRefs = browseEncodings(nodeIds, limits);
+
+ var result = new ArrayList();
+
+ for (int i = 0; i < nodeIds.size(); i++) {
+ NodeId nodeId = nodeIds.get(i);
+ int valueOffset = i * 3;
+
+ QualifiedName browseName = extractBrowseName(values.get(valueOffset));
+ Boolean isAbstract = extractIsAbstract(values.get(valueOffset + 1));
+ DataTypeDefinition definition = extractDataTypeDefinition(values.get(valueOffset + 2));
+
+ NodeId binaryEncodingId = null;
+ NodeId xmlEncodingId = null;
+ NodeId jsonEncodingId = null;
+
+ for (ReferenceDescription r : encodingRefs.get(i)) {
+ // Be lenient: also match on unqualified browse name (some servers use wrong namespace)
+ if (r.getBrowseName().equals(DataTypeEncoding.BINARY_ENCODING_NAME)
+ || Objects.equals(r.getBrowseName().name(), "Default Binary")) {
+ binaryEncodingId = r.getNodeId().toNodeId(nsTable).orElse(null);
+ } else if (r.getBrowseName().equals(DataTypeEncoding.XML_ENCODING_NAME)
+ || Objects.equals(r.getBrowseName().name(), "Default XML")) {
+ xmlEncodingId = r.getNodeId().toNodeId(nsTable).orElse(null);
+ } else if (r.getBrowseName().equals(DataTypeEncoding.JSON_ENCODING_NAME)
+ || Objects.equals(r.getBrowseName().name(), "Default JSON")) {
+ jsonEncodingId = r.getNodeId().toNodeId(nsTable).orElse(null);
+ }
+ }
+
+ result.add(
+ new ClientDataType(
+ browseName,
+ nodeId,
+ binaryEncodingId,
+ xmlEncodingId,
+ jsonEncodingId,
+ definition,
+ isAbstract));
+ }
+
+ return result;
+ }
+
+ /**
+ * Browse inverse HasSubtype references from {@code startId} until reaching a node that exists in
+ * {@code knownTypeIds}.
+ *
+ * @param startId the NodeId to start browsing from.
+ * @param knownTypeIds the set of NodeIds that are already known/loaded.
+ * @param namespaceTable the namespace table for converting ExpandedNodeIds.
+ * @return path from startId to known ancestor (inclusive), or empty list if unreachable.
+ */
+ private List browseInverseUntilKnown(
+ NodeId startId, Set knownTypeIds, NamespaceTable namespaceTable) {
+
+ List path = new ArrayList<>();
+ NodeId current = startId;
+
+ while (current != null && !knownTypeIds.contains(current)) {
+ path.add(current);
+ current = browseInverseParent(current, namespaceTable);
+ }
+
+ if (current != null && knownTypeIds.contains(current)) {
+ path.add(current);
+ return path;
+ }
+
+ return List.of();
+ }
+
+ /**
+ * Browse the inverse HasSubtype reference from {@code nodeId} to find its parent type.
+ *
+ * @param nodeId the NodeId to browse from.
+ * @param namespaceTable the namespace table for converting ExpandedNodeIds.
+ * @return the parent NodeId, or null if not found.
+ */
+ private @Nullable NodeId browseInverseParent(NodeId nodeId, NamespaceTable namespaceTable) {
+ try {
+ BrowseDescription bd =
+ new BrowseDescription(
+ nodeId,
+ BrowseDirection.Inverse,
+ NodeIds.HasSubtype,
+ false,
+ uint(NodeClass.DataType.getValue()),
+ uint(BrowseResultMask.All.getValue()));
+
+ BrowseResult result = client.browse(bd);
+
+ if (result.getStatusCode().isGood()
+ && result.getReferences() != null
+ && result.getReferences().length > 0) {
+
+ return result.getReferences()[0].getNodeId().toNodeId(namespaceTable).orElse(null);
+ }
+ } catch (UaException e) {
+ LOGGER.debug("Failed to browse inverse parent for {}: {}", nodeId, e.getMessage());
+ }
+
+ return null;
+ }
+
+ private List> browseEncodings(
+ List dataTypeIds, OperationLimits limits) {
+
+ List browseDescriptions =
+ dataTypeIds.stream()
+ .map(
+ dataTypeId ->
+ new BrowseDescription(
+ dataTypeId,
+ BrowseDirection.Forward,
+ NodeIds.HasEncoding,
+ false,
+ uint(NodeClass.Object.getValue()),
+ uint(BrowseResultMask.All.getValue())))
+ .toList();
+
+ return ClientBrowseUtils.browseWithOperationLimits(client, browseDescriptions, limits);
+ }
+
+ private static QualifiedName extractBrowseName(DataValue value) {
+ if (value.statusCode().isGood() && value.value().value() instanceof QualifiedName qn) {
+ return qn;
+ }
+ return QualifiedName.NULL_VALUE;
+ }
+
+ private static Boolean extractIsAbstract(DataValue value) {
+ if (value.statusCode().isGood() && value.value().value() instanceof Boolean b) {
+ return b;
+ }
+ return false;
+ }
+
+ private @Nullable DataTypeDefinition extractDataTypeDefinition(DataValue value) {
+ if (value.statusCode().isGood()) {
+ Object o = value.value().value();
+ if (o instanceof ExtensionObject xo) {
+ try {
+ Object decoded = xo.decode(client.getStaticEncodingContext());
+ if (decoded instanceof DataTypeDefinition dtd) {
+ return dtd;
+ }
+ } catch (Exception e) {
+ LOGGER.debug("Error decoding DataTypeDefinition: {}", e.getMessage());
+ }
+ } else if (o instanceof DataTypeDefinition dtd) {
+ return dtd;
+ }
+ }
+ return null;
+ }
+
+ // ===== Overridden Methods =====
+
+ /**
+ * Get a snapshot of the root of the underlying {@link Tree} structure.
+ *
+ * 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 {@link Tree} structure is copied, but the contained {@link DataType} instances are
+ * shared references. This is safe because {@link DataType} instances are effectively immutable.
+ *
+ * @return a snapshot copy of the root node of the underlying {@link Tree} structure.
+ */
+ @Override
+ public Tree getRoot() {
+ lock.readLock().lock();
+ try {
+ return tree.map(dataType -> dataType);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public boolean containsType(NodeId typeId) {
+ ensureResolved(typeId);
+ lock.readLock().lock();
+ try {
+ return super.containsType(typeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable DataType getType(NodeId nodeId) {
+ ensureResolved(nodeId);
+ lock.readLock().lock();
+ try {
+ return super.getType(nodeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public Class> getBackingClass(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.getBackingClass(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public OpcUaDataType getBuiltinType(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.getBuiltinType(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable DataType getDataType(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.getDataType(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable NodeId getBinaryEncodingId(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.getBinaryEncodingId(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable NodeId getXmlEncodingId(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.getXmlEncodingId(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable NodeId getJsonEncodingId(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.getJsonEncodingId(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable DataTypeDefinition getDataTypeDefinition(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.getDataTypeDefinition(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public boolean isAssignable(NodeId dataTypeId, Class> clazz) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.isAssignable(dataTypeId, clazz);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public boolean isEnumType(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.isEnumType(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public boolean isStructType(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.isStructType(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public @Nullable Tree getTreeNode(NodeId dataTypeId) {
+ ensureResolved(dataTypeId);
+ lock.readLock().lock();
+ try {
+ return super.getTreeNode(dataTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public boolean isSubtypeOf(NodeId typeId, NodeId superTypeId) {
+ ensureResolved(typeId);
+ lock.readLock().lock();
+ try {
+ return super.isSubtypeOf(typeId, superTypeId);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+}
diff --git a/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTreeSeed.java b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTreeSeed.java
new file mode 100644
index 000000000..2d274bac7
--- /dev/null
+++ b/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/typetree/LazyClientDataTypeTreeSeed.java
@@ -0,0 +1,11312 @@
+/*
+ * Copyright (c) 2025 the Eclipse Milo Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.eclipse.milo.opcua.sdk.client.typetree;
+
+import org.eclipse.milo.opcua.sdk.core.typetree.DataType;
+import org.eclipse.milo.opcua.stack.core.NodeIds;
+import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
+import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName;
+import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.StructureType;
+import org.eclipse.milo.opcua.stack.core.types.structured.EnumDefinition;
+import org.eclipse.milo.opcua.stack.core.types.structured.EnumField;
+import org.eclipse.milo.opcua.stack.core.types.structured.StructureDefinition;
+import org.eclipse.milo.opcua.stack.core.types.structured.StructureField;
+import org.eclipse.milo.opcua.stack.core.util.Tree;
+
+public final class LazyClientDataTypeTreeSeed {
+ private LazyClientDataTypeTreeSeed() {}
+
+ @SuppressWarnings("unused")
+ public static Tree createSeedTree() {
+ Tree root =
+ new Tree<>(
+ null,
+ new ClientDataType(
+ QualifiedName.parse("0:BaseDataType"),
+ NodeIds.BaseDataType,
+ null,
+ null,
+ null,
+ null,
+ true));
+ Tree booleanType =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Boolean"), NodeIds.Boolean, null, null, null, null, false));
+ Tree string =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:String"), NodeIds.String, null, null, null, null, false));
+ Tree numericRange =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:NumericRange"),
+ NodeIds.NumericRange,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree localeId =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:LocaleId"),
+ NodeIds.LocaleId,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree normalizedString =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:NormalizedString"),
+ NodeIds.NormalizedString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree decimalString =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DecimalString"),
+ NodeIds.DecimalString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree durationString =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DurationString"),
+ NodeIds.DurationString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree timeString =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:TimeString"),
+ NodeIds.TimeString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree dateString =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DateString"),
+ NodeIds.DateString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree uriString =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UriString"),
+ NodeIds.UriString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree semanticVersionString =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SemanticVersionString"),
+ NodeIds.SemanticVersionString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree encodedTicket =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EncodedTicket"),
+ NodeIds.EncodedTicket,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree trimmedString =
+ string.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:TrimmedString"),
+ NodeIds.TrimmedString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree dateTime =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DateTime"),
+ NodeIds.DateTime,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree utcTime =
+ dateTime.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UtcTime"), NodeIds.UtcTime, null, null, null, null, false));
+ Tree guid =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Guid"), NodeIds.Guid, null, null, null, null, false));
+ Tree byteString =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ByteString"),
+ NodeIds.ByteString,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree image =
+ byteString.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Image"), NodeIds.Image, null, null, null, null, true));
+ Tree imageBMP =
+ image.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ImageBMP"),
+ NodeIds.ImageBMP,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree imageGIF =
+ image.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ImageGIF"),
+ NodeIds.ImageGIF,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree imageJPG =
+ image.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ImageJPG"),
+ NodeIds.ImageJPG,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree imagePNG =
+ image.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ImagePNG"),
+ NodeIds.ImagePNG,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree applicationInstanceCertificate =
+ byteString.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ApplicationInstanceCertificate"),
+ NodeIds.ApplicationInstanceCertificate,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree continuationPoint =
+ byteString.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ContinuationPoint"),
+ NodeIds.ContinuationPoint,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree audioDataType =
+ byteString.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AudioDataType"),
+ NodeIds.AudioDataType,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree xmlElement =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:XmlElement"),
+ NodeIds.XmlElement,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree nodeId =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:NodeId"), NodeIds.NodeId, null, null, null, null, false));
+ Tree sessionAuthenticationToken =
+ nodeId.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SessionAuthenticationToken"),
+ NodeIds.SessionAuthenticationToken,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree expandedNodeId =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ExpandedNodeId"),
+ NodeIds.ExpandedNodeId,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree statusCode =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:StatusCode"),
+ NodeIds.StatusCode,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree qualifiedName =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:QualifiedName"),
+ NodeIds.QualifiedName,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree localizedText =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:LocalizedText"),
+ NodeIds.LocalizedText,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree structure =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Structure"),
+ NodeIds.Structure,
+ null,
+ null,
+ null,
+ null,
+ true));
+ createStructureNodes(structure);
+ Tree dataValue =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DataValue"),
+ NodeIds.DataValue,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree diagnosticInfo =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DiagnosticInfo"),
+ NodeIds.DiagnosticInfo,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree number =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Number"), NodeIds.Number, null, null, null, null, true));
+ Tree floatType =
+ number.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Float"), NodeIds.Float, null, null, null, null, false));
+ Tree doubleType =
+ number.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Double"), NodeIds.Double, null, null, null, null, false));
+ Tree duration =
+ doubleType.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Duration"),
+ NodeIds.Duration,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree integer =
+ number.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Integer"), NodeIds.Integer, null, null, null, null, true));
+ Tree sByte =
+ integer.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SByte"), NodeIds.SByte, null, null, null, null, false));
+ Tree int16 =
+ integer.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Int16"), NodeIds.Int16, null, null, null, null, false));
+ Tree int32 =
+ integer.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Int32"), NodeIds.Int32, null, null, null, null, false));
+ Tree int64 =
+ integer.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Int64"), NodeIds.Int64, null, null, null, null, false));
+ Tree uInteger =
+ number.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UInteger"), NodeIds.UInteger, null, null, null, null, true));
+ Tree byteType =
+ uInteger.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Byte"), NodeIds.Byte, null, null, null, null, false));
+ Tree accessLevelType =
+ byteType.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AccessLevelType"),
+ NodeIds.AccessLevelType,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree eventNotifierType =
+ byteType.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EventNotifierType"),
+ NodeIds.EventNotifierType,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree uInt16 =
+ uInteger.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UInt16"), NodeIds.UInt16, null, null, null, null, false));
+ Tree accessRestrictionType =
+ uInt16.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AccessRestrictionType"),
+ NodeIds.AccessRestrictionType,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree dataSetFieldFlags =
+ uInt16.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DataSetFieldFlags"),
+ NodeIds.DataSetFieldFlags,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree alarmMask =
+ uInt16.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AlarmMask"),
+ NodeIds.AlarmMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree uInt32 =
+ uInteger.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UInt32"), NodeIds.UInt32, null, null, null, null, false));
+ Tree permissionType =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:PermissionType"),
+ NodeIds.PermissionType,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree integerId =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:IntegerId"),
+ NodeIds.IntegerId,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree counter =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Counter"), NodeIds.Counter, null, null, null, null, false));
+ Tree attributeWriteMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AttributeWriteMask"),
+ NodeIds.AttributeWriteMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree accessLevelExType =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AccessLevelExType"),
+ NodeIds.AccessLevelExType,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree dataSetFieldContentMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DataSetFieldContentMask"),
+ NodeIds.DataSetFieldContentMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree uadpNetworkMessageContentMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UadpNetworkMessageContentMask"),
+ NodeIds.UadpNetworkMessageContentMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree uadpDataSetMessageContentMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UadpDataSetMessageContentMask"),
+ NodeIds.UadpDataSetMessageContentMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree jsonNetworkMessageContentMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:JsonNetworkMessageContentMask"),
+ NodeIds.JsonNetworkMessageContentMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree jsonDataSetMessageContentMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:JsonDataSetMessageContentMask"),
+ NodeIds.JsonDataSetMessageContentMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree index =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Index"), NodeIds.Index, null, null, null, null, false));
+ Tree lldpSystemCapabilitiesMap =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:LldpSystemCapabilitiesMap"),
+ NodeIds.LldpSystemCapabilitiesMap,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree versionTime =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:VersionTime"),
+ NodeIds.VersionTime,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree trustListValidationOptions =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:TrustListValidationOptions"),
+ NodeIds.TrustListValidationOptions,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree passwordOptionsMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:PasswordOptionsMask"),
+ NodeIds.PasswordOptionsMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree userConfigurationMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UserConfigurationMask"),
+ NodeIds.UserConfigurationMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree pubSubConfigurationRefMask =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:PubSubConfigurationRefMask"),
+ NodeIds.PubSubConfigurationRefMask,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree handle =
+ uInt32.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Handle"), NodeIds.Handle, null, null, null, null, false));
+ Tree uInt64 =
+ uInteger.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UInt64"), NodeIds.UInt64, null, null, null, null, false));
+ Tree bitFieldMaskDataType =
+ uInt64.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:BitFieldMaskDataType"),
+ NodeIds.BitFieldMaskDataType,
+ null,
+ null,
+ null,
+ null,
+ false));
+ Tree decimal =
+ number.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Decimal"), NodeIds.Decimal, null, null, null, null, false));
+ Tree enumeration =
+ root.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Enumeration"),
+ NodeIds.Enumeration,
+ null,
+ null,
+ null,
+ new EnumDefinition(new EnumField[0]),
+ true));
+ createEnumerationNodes(enumeration);
+ return root;
+ }
+
+ @SuppressWarnings("unused")
+ private static void createStructureNodes(Tree structure) {
+ Tree rolePermissionType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:RolePermissionType"),
+ NodeIds.RolePermissionType,
+ NodeIds.RolePermissionType_Encoding_DefaultBinary,
+ NodeIds.RolePermissionType_Encoding_DefaultXml,
+ NodeIds.RolePermissionType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.RolePermissionType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "RoleId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Permissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.PermissionType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree dataTypeDefinition =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DataTypeDefinition"),
+ NodeIds.DataTypeDefinition,
+ NodeIds.DataTypeDefinition_Encoding_DefaultBinary,
+ NodeIds.DataTypeDefinition_Encoding_DefaultXml,
+ NodeIds.DataTypeDefinition_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.DataTypeDefinition_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[0]),
+ true));
+ Tree structureDefinition =
+ dataTypeDefinition.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:StructureDefinition"),
+ NodeIds.StructureDefinition,
+ NodeIds.StructureDefinition_Encoding_DefaultBinary,
+ NodeIds.StructureDefinition_Encoding_DefaultXml,
+ NodeIds.StructureDefinition_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.StructureDefinition_Encoding_DefaultBinary,
+ NodeIds.DataTypeDefinition,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "DefaultEncodingId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BaseDataType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "StructureType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.StructureType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Fields",
+ LocalizedText.NULL_VALUE,
+ NodeIds.StructureField,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree enumDefinition =
+ dataTypeDefinition.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EnumDefinition"),
+ NodeIds.EnumDefinition,
+ NodeIds.EnumDefinition_Encoding_DefaultBinary,
+ NodeIds.EnumDefinition_Encoding_DefaultXml,
+ NodeIds.EnumDefinition_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EnumDefinition_Encoding_DefaultBinary,
+ NodeIds.DataTypeDefinition,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Fields",
+ LocalizedText.NULL_VALUE,
+ NodeIds.EnumField,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree structureField =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:StructureField"),
+ NodeIds.StructureField,
+ NodeIds.StructureField_Encoding_DefaultBinary,
+ NodeIds.StructureField_Encoding_DefaultXml,
+ NodeIds.StructureField_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.StructureField_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Name",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ValueRank",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ArrayDimensions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxStringLength",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsOptional",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree node =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Node"),
+ NodeIds.Node,
+ NodeIds.Node_Encoding_DefaultBinary,
+ NodeIds.Node_Encoding_DefaultXml,
+ NodeIds.Node_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.Node_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree instanceNode =
+ node.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:InstanceNode"),
+ NodeIds.InstanceNode,
+ NodeIds.InstanceNode_Encoding_DefaultBinary,
+ NodeIds.InstanceNode_Encoding_DefaultXml,
+ NodeIds.InstanceNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.InstanceNode_Encoding_DefaultBinary,
+ NodeIds.Node,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree objectNode =
+ instanceNode.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ObjectNode"),
+ NodeIds.ObjectNode,
+ NodeIds.ObjectNode_Encoding_DefaultBinary,
+ NodeIds.ObjectNode_Encoding_DefaultXml,
+ NodeIds.ObjectNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ObjectNode_Encoding_DefaultBinary,
+ NodeIds.InstanceNode,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EventNotifier",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree variableNode =
+ instanceNode.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:VariableNode"),
+ NodeIds.VariableNode,
+ NodeIds.VariableNode_Encoding_DefaultBinary,
+ NodeIds.VariableNode_Encoding_DefaultXml,
+ NodeIds.VariableNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.VariableNode_Encoding_DefaultBinary,
+ NodeIds.InstanceNode,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Value",
+ LocalizedText.NULL_VALUE,
+ NodeIds.BaseDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ValueRank",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ArrayDimensions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessLevel",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserAccessLevel",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MinimumSamplingInterval",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Duration,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Historizing",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessLevelEx",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree methodNode =
+ instanceNode.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:MethodNode"),
+ NodeIds.MethodNode,
+ NodeIds.MethodNode_Encoding_DefaultBinary,
+ NodeIds.MethodNode_Encoding_DefaultXml,
+ NodeIds.MethodNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.MethodNode_Encoding_DefaultBinary,
+ NodeIds.InstanceNode,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Executable",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserExecutable",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree viewNode =
+ instanceNode.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ViewNode"),
+ NodeIds.ViewNode,
+ NodeIds.ViewNode_Encoding_DefaultBinary,
+ NodeIds.ViewNode_Encoding_DefaultXml,
+ NodeIds.ViewNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ViewNode_Encoding_DefaultBinary,
+ NodeIds.InstanceNode,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ContainsNoLoops",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EventNotifier",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree typeNode =
+ node.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:TypeNode"),
+ NodeIds.TypeNode,
+ NodeIds.TypeNode_Encoding_DefaultBinary,
+ NodeIds.TypeNode_Encoding_DefaultXml,
+ NodeIds.TypeNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.TypeNode_Encoding_DefaultBinary,
+ NodeIds.Node,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree objectTypeNode =
+ typeNode.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ObjectTypeNode"),
+ NodeIds.ObjectTypeNode,
+ NodeIds.ObjectTypeNode_Encoding_DefaultBinary,
+ NodeIds.ObjectTypeNode_Encoding_DefaultXml,
+ NodeIds.ObjectTypeNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ObjectTypeNode_Encoding_DefaultBinary,
+ NodeIds.TypeNode,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsAbstract",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree variableTypeNode =
+ typeNode.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:VariableTypeNode"),
+ NodeIds.VariableTypeNode,
+ NodeIds.VariableTypeNode_Encoding_DefaultBinary,
+ NodeIds.VariableTypeNode_Encoding_DefaultXml,
+ NodeIds.VariableTypeNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.VariableTypeNode_Encoding_DefaultBinary,
+ NodeIds.TypeNode,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Value",
+ LocalizedText.NULL_VALUE,
+ NodeIds.BaseDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ValueRank",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ArrayDimensions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsAbstract",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree referenceTypeNode =
+ typeNode.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ReferenceTypeNode"),
+ NodeIds.ReferenceTypeNode,
+ NodeIds.ReferenceTypeNode_Encoding_DefaultBinary,
+ NodeIds.ReferenceTypeNode_Encoding_DefaultXml,
+ NodeIds.ReferenceTypeNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ReferenceTypeNode_Encoding_DefaultBinary,
+ NodeIds.TypeNode,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsAbstract",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Symmetric",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "InverseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree dataTypeNode =
+ typeNode.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DataTypeNode"),
+ NodeIds.DataTypeNode,
+ NodeIds.DataTypeNode_Encoding_DefaultBinary,
+ NodeIds.DataTypeNode_Encoding_DefaultXml,
+ NodeIds.DataTypeNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.DataTypeNode_Encoding_DefaultBinary,
+ NodeIds.TypeNode,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "References",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ReferenceNode,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AccessRestrictions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserRolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RolePermissions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RolePermissionType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserWriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteMask",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsAbstract",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataTypeDefinition",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Structure,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree referenceNode =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ReferenceNode"),
+ NodeIds.ReferenceNode,
+ NodeIds.ReferenceNode_Encoding_DefaultBinary,
+ NodeIds.ReferenceNode_Encoding_DefaultXml,
+ NodeIds.ReferenceNode_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ReferenceNode_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ReferenceTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsInverse",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TargetId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ExpandedNodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree argument =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Argument"),
+ NodeIds.Argument,
+ NodeIds.Argument_Encoding_DefaultBinary,
+ NodeIds.Argument_Encoding_DefaultXml,
+ NodeIds.Argument_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.Argument_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Name",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ValueRank",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ArrayDimensions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree statusResult =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:StatusResult"),
+ NodeIds.StatusResult,
+ NodeIds.StatusResult_Encoding_DefaultBinary,
+ NodeIds.StatusResult_Encoding_DefaultXml,
+ NodeIds.StatusResult_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.StatusResult_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "StatusCode",
+ LocalizedText.NULL_VALUE,
+ NodeIds.StatusCode,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DiagnosticInfo",
+ LocalizedText.NULL_VALUE,
+ NodeIds.DiagnosticInfo,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree userTokenPolicy =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UserTokenPolicy"),
+ NodeIds.UserTokenPolicy,
+ NodeIds.UserTokenPolicy_Encoding_DefaultBinary,
+ NodeIds.UserTokenPolicy_Encoding_DefaultXml,
+ NodeIds.UserTokenPolicy_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.UserTokenPolicy_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "PolicyId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TokenType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UserTokenType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IssuedTokenType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IssuerEndpointUrl",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityPolicyUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree applicationDescription =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ApplicationDescription"),
+ NodeIds.ApplicationDescription,
+ NodeIds.ApplicationDescription_Encoding_DefaultBinary,
+ NodeIds.ApplicationDescription_Encoding_DefaultXml,
+ NodeIds.ApplicationDescription_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ApplicationDescription_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ApplicationUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ProductUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ApplicationName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ApplicationType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ApplicationType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "GatewayServerUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DiscoveryProfileUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DiscoveryUrls",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree endpointDescription =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EndpointDescription"),
+ NodeIds.EndpointDescription,
+ NodeIds.EndpointDescription_Encoding_DefaultBinary,
+ NodeIds.EndpointDescription_Encoding_DefaultXml,
+ NodeIds.EndpointDescription_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EndpointDescription_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "EndpointUrl",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Server",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ApplicationDescription,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServerCertificate",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ApplicationInstanceCertificate,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityMode",
+ LocalizedText.NULL_VALUE,
+ NodeIds.MessageSecurityMode,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityPolicyUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserIdentityTokens",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UserTokenPolicy,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TransportProfileUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityLevel",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree userIdentityToken =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UserIdentityToken"),
+ NodeIds.UserIdentityToken,
+ NodeIds.UserIdentityToken_Encoding_DefaultBinary,
+ NodeIds.UserIdentityToken_Encoding_DefaultXml,
+ NodeIds.UserIdentityToken_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.UserIdentityToken_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "PolicyId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ true));
+ Tree anonymousIdentityToken =
+ userIdentityToken.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AnonymousIdentityToken"),
+ NodeIds.AnonymousIdentityToken,
+ NodeIds.AnonymousIdentityToken_Encoding_DefaultBinary,
+ NodeIds.AnonymousIdentityToken_Encoding_DefaultXml,
+ NodeIds.AnonymousIdentityToken_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.AnonymousIdentityToken_Encoding_DefaultBinary,
+ NodeIds.UserIdentityToken,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "PolicyId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree userNameIdentityToken =
+ userIdentityToken.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:UserNameIdentityToken"),
+ NodeIds.UserNameIdentityToken,
+ NodeIds.UserNameIdentityToken_Encoding_DefaultBinary,
+ NodeIds.UserNameIdentityToken_Encoding_DefaultXml,
+ NodeIds.UserNameIdentityToken_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.UserNameIdentityToken_Encoding_DefaultBinary,
+ NodeIds.UserIdentityToken,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "PolicyId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Password",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EncryptionAlgorithm",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree x509IdentityToken =
+ userIdentityToken.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:X509IdentityToken"),
+ NodeIds.X509IdentityToken,
+ NodeIds.X509IdentityToken_Encoding_DefaultBinary,
+ NodeIds.X509IdentityToken_Encoding_DefaultXml,
+ NodeIds.X509IdentityToken_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.X509IdentityToken_Encoding_DefaultBinary,
+ NodeIds.UserIdentityToken,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "PolicyId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CertificateData",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree issuedIdentityToken =
+ userIdentityToken.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:IssuedIdentityToken"),
+ NodeIds.IssuedIdentityToken,
+ NodeIds.IssuedIdentityToken_Encoding_DefaultBinary,
+ NodeIds.IssuedIdentityToken_Encoding_DefaultXml,
+ NodeIds.IssuedIdentityToken_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.IssuedIdentityToken_Encoding_DefaultBinary,
+ NodeIds.UserIdentityToken,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "PolicyId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TokenData",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EncryptionAlgorithm",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree endpointConfiguration =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EndpointConfiguration"),
+ NodeIds.EndpointConfiguration,
+ NodeIds.EndpointConfiguration_Encoding_DefaultBinary,
+ NodeIds.EndpointConfiguration_Encoding_DefaultXml,
+ NodeIds.EndpointConfiguration_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EndpointConfiguration_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "OperationTimeout",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UseBinaryEncoding",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxStringLength",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxByteStringLength",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxArrayLength",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxMessageSize",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxBufferSize",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ChannelLifetime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityTokenLifetime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree buildInfo =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:BuildInfo"),
+ NodeIds.BuildInfo,
+ NodeIds.BuildInfo_Encoding_DefaultBinary,
+ NodeIds.BuildInfo_Encoding_DefaultXml,
+ NodeIds.BuildInfo_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.BuildInfo_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ProductUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ManufacturerName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ProductName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SoftwareVersion",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BuildNumber",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BuildDate",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree signedSoftwareCertificate =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SignedSoftwareCertificate"),
+ NodeIds.SignedSoftwareCertificate,
+ NodeIds.SignedSoftwareCertificate_Encoding_DefaultBinary,
+ NodeIds.SignedSoftwareCertificate_Encoding_DefaultXml,
+ NodeIds.SignedSoftwareCertificate_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.SignedSoftwareCertificate_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "CertificateData",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Signature",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree addNodesItem =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AddNodesItem"),
+ NodeIds.AddNodesItem,
+ NodeIds.AddNodesItem_Encoding_DefaultBinary,
+ NodeIds.AddNodesItem_Encoding_DefaultXml,
+ NodeIds.AddNodesItem_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.AddNodesItem_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ParentNodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ExpandedNodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ReferenceTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RequestedNewNodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ExpandedNodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NodeAttributes",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Structure,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TypeDefinition",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ExpandedNodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree addReferencesItem =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AddReferencesItem"),
+ NodeIds.AddReferencesItem,
+ NodeIds.AddReferencesItem_Encoding_DefaultBinary,
+ NodeIds.AddReferencesItem_Encoding_DefaultXml,
+ NodeIds.AddReferencesItem_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.AddReferencesItem_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "SourceNodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ReferenceTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsForward",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TargetServerUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TargetNodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ExpandedNodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TargetNodeClass",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeClass,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree deleteNodesItem =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DeleteNodesItem"),
+ NodeIds.DeleteNodesItem,
+ NodeIds.DeleteNodesItem_Encoding_DefaultBinary,
+ NodeIds.DeleteNodesItem_Encoding_DefaultXml,
+ NodeIds.DeleteNodesItem_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.DeleteNodesItem_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DeleteTargetReferences",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree deleteReferencesItem =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DeleteReferencesItem"),
+ NodeIds.DeleteReferencesItem,
+ NodeIds.DeleteReferencesItem_Encoding_DefaultBinary,
+ NodeIds.DeleteReferencesItem_Encoding_DefaultXml,
+ NodeIds.DeleteReferencesItem_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.DeleteReferencesItem_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "SourceNodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ReferenceTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsForward",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TargetNodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ExpandedNodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DeleteBidirectional",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree registeredServer =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:RegisteredServer"),
+ NodeIds.RegisteredServer,
+ NodeIds.RegisteredServer_Encoding_DefaultBinary,
+ NodeIds.RegisteredServer_Encoding_DefaultXml,
+ NodeIds.RegisteredServer_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.RegisteredServer_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ServerUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ProductUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServerNames",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServerType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ApplicationType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "GatewayServerUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DiscoveryUrls",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SemaphoreFilePath",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsOnline",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree relativePathElement =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:RelativePathElement"),
+ NodeIds.RelativePathElement,
+ NodeIds.RelativePathElement_Encoding_DefaultBinary,
+ NodeIds.RelativePathElement_Encoding_DefaultXml,
+ NodeIds.RelativePathElement_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.RelativePathElement_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ReferenceTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IsInverse",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IncludeSubtypes",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TargetName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree relativePath =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:RelativePath"),
+ NodeIds.RelativePath,
+ NodeIds.RelativePath_Encoding_DefaultBinary,
+ NodeIds.RelativePath_Encoding_DefaultXml,
+ NodeIds.RelativePath_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.RelativePath_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Elements",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RelativePathElement,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree contentFilterElement =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ContentFilterElement"),
+ NodeIds.ContentFilterElement,
+ NodeIds.ContentFilterElement_Encoding_DefaultBinary,
+ NodeIds.ContentFilterElement_Encoding_DefaultXml,
+ NodeIds.ContentFilterElement_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ContentFilterElement_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "FilterOperator",
+ LocalizedText.NULL_VALUE,
+ NodeIds.FilterOperator,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "FilterOperands",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Structure,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree contentFilter =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ContentFilter"),
+ NodeIds.ContentFilter,
+ NodeIds.ContentFilter_Encoding_DefaultBinary,
+ NodeIds.ContentFilter_Encoding_DefaultXml,
+ NodeIds.ContentFilter_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ContentFilter_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Elements",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ContentFilterElement,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree filterOperand =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:FilterOperand"),
+ NodeIds.FilterOperand,
+ NodeIds.FilterOperand_Encoding_DefaultBinary,
+ NodeIds.FilterOperand_Encoding_DefaultXml,
+ NodeIds.FilterOperand_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.FilterOperand_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[0]),
+ true));
+ Tree elementOperand =
+ filterOperand.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ElementOperand"),
+ NodeIds.ElementOperand,
+ NodeIds.ElementOperand_Encoding_DefaultBinary,
+ NodeIds.ElementOperand_Encoding_DefaultXml,
+ NodeIds.ElementOperand_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ElementOperand_Encoding_DefaultBinary,
+ NodeIds.FilterOperand,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Index",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree literalOperand =
+ filterOperand.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:LiteralOperand"),
+ NodeIds.LiteralOperand,
+ NodeIds.LiteralOperand_Encoding_DefaultBinary,
+ NodeIds.LiteralOperand_Encoding_DefaultXml,
+ NodeIds.LiteralOperand_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.LiteralOperand_Encoding_DefaultBinary,
+ NodeIds.FilterOperand,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Value",
+ LocalizedText.NULL_VALUE,
+ NodeIds.BaseDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree attributeOperand =
+ filterOperand.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AttributeOperand"),
+ NodeIds.AttributeOperand,
+ NodeIds.AttributeOperand_Encoding_DefaultBinary,
+ NodeIds.AttributeOperand_Encoding_DefaultXml,
+ NodeIds.AttributeOperand_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.AttributeOperand_Encoding_DefaultBinary,
+ NodeIds.FilterOperand,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "NodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Alias",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowsePath",
+ LocalizedText.NULL_VALUE,
+ NodeIds.RelativePath,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AttributeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.IntegerId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IndexRange",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NumericRange,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree simpleAttributeOperand =
+ filterOperand.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SimpleAttributeOperand"),
+ NodeIds.SimpleAttributeOperand,
+ NodeIds.SimpleAttributeOperand_Encoding_DefaultBinary,
+ NodeIds.SimpleAttributeOperand_Encoding_DefaultXml,
+ NodeIds.SimpleAttributeOperand_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.SimpleAttributeOperand_Encoding_DefaultBinary,
+ NodeIds.FilterOperand,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "TypeDefinitionId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowsePath",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AttributeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.IntegerId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IndexRange",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NumericRange,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree historyEvent =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:HistoryEvent"),
+ NodeIds.HistoryEvent,
+ NodeIds.HistoryEvent_Encoding_DefaultBinary,
+ NodeIds.HistoryEvent_Encoding_DefaultXml,
+ NodeIds.HistoryEvent_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.HistoryEvent_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Events",
+ LocalizedText.NULL_VALUE,
+ NodeIds.HistoryEventFieldList,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree historyModifiedEvent =
+ historyEvent.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:HistoryModifiedEvent"),
+ NodeIds.HistoryModifiedEvent,
+ NodeIds.HistoryModifiedEvent_Encoding_DefaultBinary,
+ NodeIds.HistoryModifiedEvent_Encoding_DefaultXml,
+ NodeIds.HistoryModifiedEvent_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.HistoryModifiedEvent_Encoding_DefaultBinary,
+ NodeIds.HistoryEvent,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Events",
+ LocalizedText.NULL_VALUE,
+ NodeIds.HistoryEventFieldList,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ModificationInfos",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ModificationInfo,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree monitoringFilter =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:MonitoringFilter"),
+ NodeIds.MonitoringFilter,
+ NodeIds.MonitoringFilter_Encoding_DefaultBinary,
+ NodeIds.MonitoringFilter_Encoding_DefaultXml,
+ NodeIds.MonitoringFilter_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.MonitoringFilter_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[0]),
+ false));
+ Tree eventFilter =
+ monitoringFilter.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EventFilter"),
+ NodeIds.EventFilter,
+ NodeIds.EventFilter_Encoding_DefaultBinary,
+ NodeIds.EventFilter_Encoding_DefaultXml,
+ NodeIds.EventFilter_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EventFilter_Encoding_DefaultBinary,
+ NodeIds.MonitoringFilter,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "SelectClauses",
+ LocalizedText.NULL_VALUE,
+ NodeIds.SimpleAttributeOperand,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WhereClause",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ContentFilter,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree redundantServerDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:RedundantServerDataType"),
+ NodeIds.RedundantServerDataType,
+ NodeIds.RedundantServerDataType_Encoding_DefaultBinary,
+ NodeIds.RedundantServerDataType_Encoding_DefaultXml,
+ NodeIds.RedundantServerDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.RedundantServerDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ServerId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServiceLevel",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServerState",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServerState,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree samplingIntervalDiagnosticsDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SamplingIntervalDiagnosticsDataType"),
+ NodeIds.SamplingIntervalDiagnosticsDataType,
+ NodeIds.SamplingIntervalDiagnosticsDataType_Encoding_DefaultBinary,
+ NodeIds.SamplingIntervalDiagnosticsDataType_Encoding_DefaultXml,
+ NodeIds.SamplingIntervalDiagnosticsDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.SamplingIntervalDiagnosticsDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "SamplingInterval",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Duration,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MonitoredItemCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxMonitoredItemCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisabledMonitoredItemCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree serverDiagnosticsSummaryDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ServerDiagnosticsSummaryDataType"),
+ NodeIds.ServerDiagnosticsSummaryDataType,
+ NodeIds.ServerDiagnosticsSummaryDataType_Encoding_DefaultBinary,
+ NodeIds.ServerDiagnosticsSummaryDataType_Encoding_DefaultXml,
+ NodeIds.ServerDiagnosticsSummaryDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ServerDiagnosticsSummaryDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ServerViewCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CurrentSessionCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CumulatedSessionCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityRejectedSessionCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RejectedSessionCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SessionTimeoutCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SessionAbortCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CurrentSubscriptionCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CumulatedSubscriptionCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "PublishingIntervalCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityRejectedRequestsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RejectedRequestsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree serverStatusDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ServerStatusDataType"),
+ NodeIds.ServerStatusDataType,
+ NodeIds.ServerStatusDataType_Encoding_DefaultBinary,
+ NodeIds.ServerStatusDataType_Encoding_DefaultXml,
+ NodeIds.ServerStatusDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ServerStatusDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "StartTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CurrentTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "State",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServerState,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BuildInfo",
+ LocalizedText.NULL_VALUE,
+ NodeIds.BuildInfo,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecondsTillShutdown",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ShutdownReason",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree sessionDiagnosticsDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SessionDiagnosticsDataType"),
+ NodeIds.SessionDiagnosticsDataType,
+ NodeIds.SessionDiagnosticsDataType_Encoding_DefaultBinary,
+ NodeIds.SessionDiagnosticsDataType_Encoding_DefaultXml,
+ NodeIds.SessionDiagnosticsDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.SessionDiagnosticsDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "SessionId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SessionName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ClientDescription",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ApplicationDescription,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServerUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EndpointUrl",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LocaleIds",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocaleId,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ActualSessionTimeout",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Duration,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxResponseMessageSize",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ClientConnectionTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ClientLastContactTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CurrentSubscriptionsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CurrentMonitoredItemsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CurrentPublishRequestsInQueue",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TotalRequestCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UnauthorizedRequestCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ReadCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "HistoryReadCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "HistoryUpdateCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CallCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CreateMonitoredItemsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ModifyMonitoredItemsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SetMonitoringModeCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SetTriggeringCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DeleteMonitoredItemsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CreateSubscriptionCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ModifySubscriptionCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SetPublishingModeCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "PublishCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RepublishCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TransferSubscriptionsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DeleteSubscriptionsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AddNodesCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AddReferencesCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DeleteNodesCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DeleteReferencesCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BrowseNextCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TranslateBrowsePathsToNodeIdsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "QueryFirstCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "QueryNextCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RegisterNodesCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UnregisterNodesCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ServiceCounterDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree sessionSecurityDiagnosticsDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SessionSecurityDiagnosticsDataType"),
+ NodeIds.SessionSecurityDiagnosticsDataType,
+ NodeIds.SessionSecurityDiagnosticsDataType_Encoding_DefaultBinary,
+ NodeIds.SessionSecurityDiagnosticsDataType_Encoding_DefaultXml,
+ NodeIds.SessionSecurityDiagnosticsDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.SessionSecurityDiagnosticsDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "SessionId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ClientUserIdOfSession",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ClientUserIdHistory",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AuthenticationMechanism",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Encoding",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TransportProtocol",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityMode",
+ LocalizedText.NULL_VALUE,
+ NodeIds.MessageSecurityMode,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SecurityPolicyUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ClientCertificate",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree serviceCounterDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ServiceCounterDataType"),
+ NodeIds.ServiceCounterDataType,
+ NodeIds.ServiceCounterDataType_Encoding_DefaultBinary,
+ NodeIds.ServiceCounterDataType_Encoding_DefaultXml,
+ NodeIds.ServiceCounterDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ServiceCounterDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "TotalCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ErrorCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree subscriptionDiagnosticsDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SubscriptionDiagnosticsDataType"),
+ NodeIds.SubscriptionDiagnosticsDataType,
+ NodeIds.SubscriptionDiagnosticsDataType_Encoding_DefaultBinary,
+ NodeIds.SubscriptionDiagnosticsDataType_Encoding_DefaultXml,
+ NodeIds.SubscriptionDiagnosticsDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.SubscriptionDiagnosticsDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "SessionId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SubscriptionId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Priority",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "PublishingInterval",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Duration,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxKeepAliveCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxLifetimeCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxNotificationsPerPublish",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "PublishingEnabled",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ModifyCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EnableCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisableCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RepublishRequestCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RepublishMessageRequestCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "RepublishMessageCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TransferRequestCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TransferredToAltClientCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TransferredToSameClientCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "PublishRequestCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataChangeNotificationsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EventNotificationsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NotificationsCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LatePublishRequestCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CurrentKeepAliveCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CurrentLifetimeCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UnacknowledgedMessageCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DiscardedMessageCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MonitoredItemCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisabledMonitoredItemCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MonitoringQueueOverflowCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NextSequenceNumber",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EventQueueOverflowCount",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree modelChangeStructureDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ModelChangeStructureDataType"),
+ NodeIds.ModelChangeStructureDataType,
+ NodeIds.ModelChangeStructureDataType_Encoding_DefaultBinary,
+ NodeIds.ModelChangeStructureDataType_Encoding_DefaultXml,
+ NodeIds.ModelChangeStructureDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ModelChangeStructureDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Affected",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AffectedType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Verb",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree range =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Range"),
+ NodeIds.Range,
+ NodeIds.Range_Encoding_DefaultBinary,
+ NodeIds.Range_Encoding_DefaultXml,
+ NodeIds.Range_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.Range_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Low",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Double,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "High",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Double,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree eUInformation =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EUInformation"),
+ NodeIds.EUInformation,
+ NodeIds.EUInformation_Encoding_DefaultBinary,
+ NodeIds.EUInformation_Encoding_DefaultXml,
+ NodeIds.EUInformation_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EUInformation_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "NamespaceUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UnitId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree annotation =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Annotation"),
+ NodeIds.Annotation,
+ NodeIds.Annotation_Encoding_DefaultBinary,
+ NodeIds.Annotation_Encoding_DefaultXml,
+ NodeIds.Annotation_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.Annotation_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Message",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AnnotationTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree programDiagnosticDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ProgramDiagnosticDataType"),
+ NodeIds.ProgramDiagnosticDataType,
+ NodeIds.ProgramDiagnosticDataType_Encoding_DefaultBinary,
+ NodeIds.ProgramDiagnosticDataType_Encoding_DefaultXml,
+ NodeIds.ProgramDiagnosticDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ProgramDiagnosticDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "CreateSessionId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "CreateClientName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "InvocationCreationTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LastTransitionTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LastMethodCall",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LastMethodSessionId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LastMethodInputArguments",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Argument,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LastMethodOutputArguments",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Argument,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LastMethodCallTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "LastMethodReturnStatus",
+ LocalizedText.NULL_VALUE,
+ NodeIds.StatusResult,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree semanticChangeStructureDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SemanticChangeStructureDataType"),
+ NodeIds.SemanticChangeStructureDataType,
+ NodeIds.SemanticChangeStructureDataType_Encoding_DefaultBinary,
+ NodeIds.SemanticChangeStructureDataType_Encoding_DefaultXml,
+ NodeIds.SemanticChangeStructureDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.SemanticChangeStructureDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Affected",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AffectedType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree historyEventFieldList =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:HistoryEventFieldList"),
+ NodeIds.HistoryEventFieldList,
+ NodeIds.HistoryEventFieldList_Encoding_DefaultBinary,
+ NodeIds.HistoryEventFieldList_Encoding_DefaultXml,
+ NodeIds.HistoryEventFieldList_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.HistoryEventFieldList_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "EventFields",
+ LocalizedText.NULL_VALUE,
+ NodeIds.BaseDataType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree aggregateConfiguration =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AggregateConfiguration"),
+ NodeIds.AggregateConfiguration,
+ NodeIds.AggregateConfiguration_Encoding_DefaultBinary,
+ NodeIds.AggregateConfiguration_Encoding_DefaultXml,
+ NodeIds.AggregateConfiguration_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.AggregateConfiguration_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "UseServerCapabilitiesDefaults",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TreatUncertainAsBad",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "PercentDataBad",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "PercentDataGood",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UseSlopedExtrapolation",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree enumValueType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EnumValueType"),
+ NodeIds.EnumValueType,
+ NodeIds.EnumValueType_Encoding_DefaultBinary,
+ NodeIds.EnumValueType_Encoding_DefaultXml,
+ NodeIds.EnumValueType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EnumValueType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Value",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int64,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree enumField =
+ enumValueType.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EnumField"),
+ NodeIds.EnumField,
+ NodeIds.EnumField_Encoding_DefaultBinary,
+ NodeIds.EnumField_Encoding_DefaultXml,
+ NodeIds.EnumField_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EnumField_Encoding_DefaultBinary,
+ NodeIds.EnumValueType,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DisplayName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Value",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int64,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Name",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree timeZoneDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:TimeZoneDataType"),
+ NodeIds.TimeZoneDataType,
+ NodeIds.TimeZoneDataType_Encoding_DefaultBinary,
+ NodeIds.TimeZoneDataType_Encoding_DefaultXml,
+ NodeIds.TimeZoneDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.TimeZoneDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Offset",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int16,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DaylightSavingInOffset",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Boolean,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree modificationInfo =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ModificationInfo"),
+ NodeIds.ModificationInfo,
+ NodeIds.ModificationInfo_Encoding_DefaultBinary,
+ NodeIds.ModificationInfo_Encoding_DefaultXml,
+ NodeIds.ModificationInfo_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ModificationInfo_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ModificationTime",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UtcTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UpdateType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.HistoryUpdateType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "UserName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree endpointUrlListDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EndpointUrlListDataType"),
+ NodeIds.EndpointUrlListDataType,
+ NodeIds.EndpointUrlListDataType_Encoding_DefaultBinary,
+ NodeIds.EndpointUrlListDataType_Encoding_DefaultXml,
+ NodeIds.EndpointUrlListDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EndpointUrlListDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "EndpointUrlList",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree networkGroupDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:NetworkGroupDataType"),
+ NodeIds.NetworkGroupDataType,
+ NodeIds.NetworkGroupDataType_Encoding_DefaultBinary,
+ NodeIds.NetworkGroupDataType_Encoding_DefaultXml,
+ NodeIds.NetworkGroupDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.NetworkGroupDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "ServerUri",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "NetworkPaths",
+ LocalizedText.NULL_VALUE,
+ NodeIds.EndpointUrlListDataType,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree axisInformation =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:AxisInformation"),
+ NodeIds.AxisInformation,
+ NodeIds.AxisInformation_Encoding_DefaultBinary,
+ NodeIds.AxisInformation_Encoding_DefaultXml,
+ NodeIds.AxisInformation_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.AxisInformation_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "EngineeringUnits",
+ LocalizedText.NULL_VALUE,
+ NodeIds.EUInformation,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EURange",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Range,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Title",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AxisScaleType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.AxisScaleEnumeration,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AxisSteps",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Double,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree xVType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:XVType"),
+ NodeIds.XVType,
+ NodeIds.XVType_Encoding_DefaultBinary,
+ NodeIds.XVType_Encoding_DefaultXml,
+ NodeIds.XVType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.XVType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "X",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Double,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Value",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Float,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree complexNumberType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ComplexNumberType"),
+ NodeIds.ComplexNumberType,
+ NodeIds.ComplexNumberType_Encoding_DefaultBinary,
+ NodeIds.ComplexNumberType_Encoding_DefaultXml,
+ NodeIds.ComplexNumberType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ComplexNumberType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Real",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Float,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Imaginary",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Float,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree doubleComplexNumberType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DoubleComplexNumberType"),
+ NodeIds.DoubleComplexNumberType,
+ NodeIds.DoubleComplexNumberType_Encoding_DefaultBinary,
+ NodeIds.DoubleComplexNumberType_Encoding_DefaultXml,
+ NodeIds.DoubleComplexNumberType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.DoubleComplexNumberType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Real",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Double,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Imaginary",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Double,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree serverOnNetwork =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ServerOnNetwork"),
+ NodeIds.ServerOnNetwork,
+ NodeIds.ServerOnNetwork_Encoding_DefaultBinary,
+ NodeIds.ServerOnNetwork_Encoding_DefaultXml,
+ NodeIds.ServerOnNetwork_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ServerOnNetwork_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "RecordId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServerName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DiscoveryUrl",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServerCapabilities",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree trustListDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:TrustListDataType"),
+ NodeIds.TrustListDataType,
+ NodeIds.TrustListDataType_Encoding_DefaultBinary,
+ NodeIds.TrustListDataType_Encoding_DefaultXml,
+ NodeIds.TrustListDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.TrustListDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "SpecifiedLists",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TrustedCertificates",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TrustedCrls",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IssuerCertificates",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IssuerCrls",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree optionSet =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:OptionSet"),
+ NodeIds.OptionSet,
+ NodeIds.OptionSet_Encoding_DefaultBinary,
+ NodeIds.OptionSet_Encoding_DefaultXml,
+ NodeIds.OptionSet_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.OptionSet_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Value",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ValidBits",
+ LocalizedText.NULL_VALUE,
+ NodeIds.ByteString,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ true));
+ Tree union =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:Union"),
+ NodeIds.Union,
+ NodeIds.Union_Encoding_DefaultBinary,
+ NodeIds.Union_Encoding_DefaultXml,
+ NodeIds.Union_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.Union_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[0]),
+ true));
+ Tree discoveryConfiguration =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DiscoveryConfiguration"),
+ NodeIds.DiscoveryConfiguration,
+ NodeIds.DiscoveryConfiguration_Encoding_DefaultBinary,
+ NodeIds.DiscoveryConfiguration_Encoding_DefaultXml,
+ NodeIds.DiscoveryConfiguration_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.DiscoveryConfiguration_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[0]),
+ false));
+ Tree mdnsDiscoveryConfiguration =
+ discoveryConfiguration.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:MdnsDiscoveryConfiguration"),
+ NodeIds.MdnsDiscoveryConfiguration,
+ NodeIds.MdnsDiscoveryConfiguration_Encoding_DefaultBinary,
+ NodeIds.MdnsDiscoveryConfiguration_Encoding_DefaultXml,
+ NodeIds.MdnsDiscoveryConfiguration_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.MdnsDiscoveryConfiguration_Encoding_DefaultBinary,
+ NodeIds.DiscoveryConfiguration,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "MdnsServerName",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ServerCapabilities",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree publishedVariableDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:PublishedVariableDataType"),
+ NodeIds.PublishedVariableDataType,
+ NodeIds.PublishedVariableDataType_Encoding_DefaultBinary,
+ NodeIds.PublishedVariableDataType_Encoding_DefaultXml,
+ NodeIds.PublishedVariableDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.PublishedVariableDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "PublishedVariable",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AttributeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.IntegerId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SamplingIntervalHint",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Duration,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DeadbandType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DeadbandValue",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Double,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "IndexRange",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NumericRange,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "SubstituteValue",
+ LocalizedText.NULL_VALUE,
+ NodeIds.BaseDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MetaDataProperties",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree fieldMetaData =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:FieldMetaData"),
+ NodeIds.FieldMetaData,
+ NodeIds.FieldMetaData_Encoding_DefaultBinary,
+ NodeIds.FieldMetaData_Encoding_DefaultXml,
+ NodeIds.FieldMetaData_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.FieldMetaData_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Name",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Description",
+ LocalizedText.NULL_VALUE,
+ NodeIds.LocalizedText,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "FieldFlags",
+ LocalizedText.NULL_VALUE,
+ NodeIds.DataSetFieldFlags,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BuiltInType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ValueRank",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Int32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ArrayDimensions",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MaxStringLength",
+ LocalizedText.NULL_VALUE,
+ NodeIds.UInt32,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataSetFieldId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Guid,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Properties",
+ LocalizedText.NULL_VALUE,
+ NodeIds.KeyValuePair,
+ 1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree dataTypeDescription =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:DataTypeDescription"),
+ NodeIds.DataTypeDescription,
+ NodeIds.DataTypeDescription_Encoding_DefaultBinary,
+ NodeIds.DataTypeDescription_Encoding_DefaultXml,
+ NodeIds.DataTypeDescription_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.DataTypeDescription_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "DataTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Name",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ true));
+ Tree simpleTypeDescription =
+ dataTypeDescription.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:SimpleTypeDescription"),
+ NodeIds.SimpleTypeDescription,
+ NodeIds.SimpleTypeDescription_Encoding_DefaultBinary,
+ NodeIds.SimpleTypeDescription_Encoding_DefaultXml,
+ NodeIds.SimpleTypeDescription_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.SimpleTypeDescription_Encoding_DefaultBinary,
+ NodeIds.DataTypeDescription,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Name",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BaseDataType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BuiltInType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree structureDescription =
+ dataTypeDescription.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:StructureDescription"),
+ NodeIds.StructureDescription,
+ NodeIds.StructureDescription_Encoding_DefaultBinary,
+ NodeIds.StructureDescription_Encoding_DefaultXml,
+ NodeIds.StructureDescription_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.StructureDescription_Encoding_DefaultBinary,
+ NodeIds.DataTypeDescription,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Name",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "StructureDefinition",
+ LocalizedText.NULL_VALUE,
+ NodeIds.StructureDefinition,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree enumDescription =
+ dataTypeDescription.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:EnumDescription"),
+ NodeIds.EnumDescription,
+ NodeIds.EnumDescription_Encoding_DefaultBinary,
+ NodeIds.EnumDescription_Encoding_DefaultXml,
+ NodeIds.EnumDescription_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.EnumDescription_Encoding_DefaultBinary,
+ NodeIds.DataTypeDescription,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Name",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "DataTypeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "EnumDefinition",
+ LocalizedText.NULL_VALUE,
+ NodeIds.EnumDefinition,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "BuiltInType",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Byte,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree keyValuePair =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:KeyValuePair"),
+ NodeIds.KeyValuePair,
+ NodeIds.KeyValuePair_Encoding_DefaultBinary,
+ NodeIds.KeyValuePair_Encoding_DefaultXml,
+ NodeIds.KeyValuePair_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.KeyValuePair_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "Key",
+ LocalizedText.NULL_VALUE,
+ NodeIds.QualifiedName,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "Value",
+ LocalizedText.NULL_VALUE,
+ NodeIds.BaseDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree configurationVersionDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:ConfigurationVersionDataType"),
+ NodeIds.ConfigurationVersionDataType,
+ NodeIds.ConfigurationVersionDataType_Encoding_DefaultBinary,
+ NodeIds.ConfigurationVersionDataType_Encoding_DefaultXml,
+ NodeIds.ConfigurationVersionDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.ConfigurationVersionDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "MajorVersion",
+ LocalizedText.NULL_VALUE,
+ NodeIds.VersionTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "MinorVersion",
+ LocalizedText.NULL_VALUE,
+ NodeIds.VersionTime,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree fieldTargetDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:FieldTargetDataType"),
+ NodeIds.FieldTargetDataType,
+ NodeIds.FieldTargetDataType_Encoding_DefaultBinary,
+ NodeIds.FieldTargetDataType_Encoding_DefaultXml,
+ NodeIds.FieldTargetDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.FieldTargetDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "DataSetFieldId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.Guid,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "ReceiverIndexRange",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NumericRange,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "TargetNodeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NodeId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "AttributeId",
+ LocalizedText.NULL_VALUE,
+ NodeIds.IntegerId,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "WriteIndexRange",
+ LocalizedText.NULL_VALUE,
+ NodeIds.NumericRange,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "OverrideValueHandling",
+ LocalizedText.NULL_VALUE,
+ NodeIds.OverrideValueHandling,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false),
+ new StructureField(
+ "OverrideValue",
+ LocalizedText.NULL_VALUE,
+ NodeIds.BaseDataType,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ false));
+ Tree networkAddressDataType =
+ structure.addChild(
+ new ClientDataType(
+ QualifiedName.parse("0:NetworkAddressDataType"),
+ NodeIds.NetworkAddressDataType,
+ NodeIds.NetworkAddressDataType_Encoding_DefaultBinary,
+ NodeIds.NetworkAddressDataType_Encoding_DefaultXml,
+ NodeIds.NetworkAddressDataType_Encoding_DefaultJson,
+ new StructureDefinition(
+ NodeIds.NetworkAddressDataType_Encoding_DefaultBinary,
+ NodeIds.Structure,
+ StructureType.Structure,
+ new StructureField[] {
+ new StructureField(
+ "NetworkInterface",
+ LocalizedText.NULL_VALUE,
+ NodeIds.String,
+ -1,
+ null,
+ UInteger.valueOf(0),
+ false)
+ }),
+ true));
+ Tree