Skip to content

Conversation

@kevinherron
Copy link
Contributor

@kevinherron kevinherron commented Dec 11, 2025

Summary

  • Add LazyClientDataTypeTree that resolves types on demand by browsing inverse HasSubtype references, avoiding eager enumeration of the entire type hierarchy
  • Add DataTypeTreeFactory interface with eager() and lazy() factory methods for configuring how the DataTypeTree is created
  • Add setDataTypeTreeFactory() method to OpcUaClient to allow switching between eager and lazy tree implementations
  • Extract shared browse/read utilities into ClientBrowseUtils class with operation limit handling
  • Refactor DataTypeTreeBuilder, ObjectTypeTreeBuilder, and VariableTypeTreeBuilder to use shared utilities
  • Add LazyClientDataTypeManager that resolves codecs on demand when types are requested
  • Add DataTypeManagerFactory interface with eager() and lazy() factory methods for configuring how the DataTypeManager is created
  • Replace setDataTypeManagerInitializer() with setDynamicDataTypeManagerFactory() for greater flexibility

Breaking Changes

The OpcUaClient.setDataTypeManagerInitializer() method has been replaced with setDynamicDataTypeManagerFactory() to support both eager and lazy codec resolution strategies.

Before After
OpcUaClient.DataTypeManagerInitializer DataTypeManagerFactory.Initializer
OpcUaClient.DefaultDataTypeManagerInitializer DataTypeManagerFactory.DefaultInitializer
setDataTypeManagerInitializer(initializer) setDynamicDataTypeManagerFactory(DataTypeManagerFactory.eager(initializer))

Migration Examples

Custom initializer (e.g., legacy DTD support):

// Before
client.setDataTypeManagerInitializer(new LegacyDataTypeManagerInitializer(client));

// After
client.setDynamicDataTypeManagerFactory(
    DataTypeManagerFactory.eager(new LegacyDataTypeManagerInitializer(client))
);

Custom codec factory:

// Before
client.setDataTypeManagerInitializer(
    new OpcUaClient.DefaultDataTypeManagerInitializer(MyCodecFactory::create)
);

// After
client.setDynamicDataTypeManagerFactory(
    DataTypeManagerFactory.eager(MyCodecFactory::create)
);

Lazy resolution (new feature):

client.setDataTypeTreeFactory(DataTypeTreeFactory.lazy());
client.setDynamicDataTypeManagerFactory(DataTypeManagerFactory.lazy());

- Add LazyClientDataTypeTree that resolves types on demand by browsing
  inverse HasSubtype references, avoiding eager enumeration of the
  entire type hierarchy
- Add DataTypeTreeFactory interface with eager() and lazy() factory
  methods for configuring how the DataTypeTree is created
- Add setDataTypeTreeFactory() method to OpcUaClient to allow switching
  between eager and lazy tree implementations
- Add LazyTypeTreeUtils for batched browse and read operations with
  operation limit handling
- Update OpcUaClient.getDataTypeTree() to use the configured factory
  instead of calling DataTypeTreeBuilder.build() directly
- Include integration tests for LazyClientDataTypeTree and
  DataTypeTreeFactory
- Add ClientBrowseUtils class with methods for browse and read
  operations with operation limit handling
- Refactor DataTypeTreeBuilder to use shared utilities and
  OperationLimits
- Refactor ObjectTypeTreeBuilder to use shared utilities and
  OperationLimits
- Refactor VariableTypeTreeBuilder to use shared utilities and
  OperationLimits
- Simplify LazyTypeTreeUtils by delegating to ClientBrowseUtils
- Call client.getOperationLimits() directly in tree builders
- Delete redundant wrapper method from ClientBrowseUtils
@kevinherron kevinherron marked this pull request as draft December 11, 2025 01:44
- Add LazyClientDataTypeTreeSeed with pre-populated primitive types
  and their subtypes (String, DateTime, ByteString, Number, etc.)
- Structure and Enumeration base nodes are seeded without subtypes
- Add SeededLazyClientDataTypeTreeTest to verify seeded tree behavior
@kevinherron kevinherron marked this pull request as ready for review December 11, 2025 16:02
- Move browseInverseUntilKnown and browseInverseParent into
  LazyClientDataTypeTree as private instance methods
- Call ClientBrowseUtils directly instead of through LazyTypeTreeUtils
@kevinherron kevinherron marked this pull request as draft December 12, 2025 13:47
- Add DataTypeManagerFactory interface to abstract DataTypeManager creation
- Add LazyClientDataTypeManager that resolves codecs on demand
- Move DefaultDataTypeManagerInitializer to DataTypeManagerFactory.DefaultInitializer
- Replace setDataTypeManagerInitializer with setDynamicDataTypeManagerFactory
- Update LegacyDataTypeManagerInitializer to implement Initializer interface
- Update example to use new factory API
@kevinherron kevinherron marked this pull request as ready for review December 12, 2025 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants