Avatar

Please consider registering
guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed Topic RSS sp_TopicIcon
NodeBuilder for optional object nodes
May 17, 2018
8:40, EEST
Avatar
hbrackel
Member
Members
Forum Posts: 144
Member Since:
February 21, 2014
sp_UserOfflineSmall Offline

Good morning,

I have generated code, which comprises object nodes, which have optional objectNode children, which in turn have optional variables. While the use of the TypeDefinitionBasedNodeBuilderConfiguration as described in the server tutorial works well for child variables, I wasn’t successful in creating child objects this way. So my question is, how can I configure the node builder for optional object nodes and in turn their children? (possibly even a deeper hierarchy).

Thanks,
Hans-Uwe

PS: I’m using SDK 3.0.0

May 17, 2018
10:57, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi Hans-Uwe,

In general it should not be any difference about Variables vs. Objects in this case. As a test, does the node appear, if you set the setInstantiateAllOptionals(true) in the TypeDefinitionBasedNodeBuilderConfiguration builder?

However depending on how the type is defined, it might fall into another (complex) category, in short:
Let A be type that has an optional node X having TypeDefinition B.
Let B be type that has an optional node Y having TypeDefinition C.

It is possible to construct the nodes for type A in 2 different ways.
1A: A -HasComponent-> X (Typedef B) -HasComponent-> Y (Typedef C)
1B: B -HasComponent-> Y (Typedef C)
1C: C

2A: A -HasComponent-> X (Typedef B) (note missing reference to Y here)
2B: B -HasComponent-> Y (Typedef C)
2C: C

The short answer is that if A is defined as in 1A, then it is possible to instantiate A with C with NodeBuilder. However if it is defined as 2A, then by default it is not possible. (longer is that is is doable, but there are some edge-cases and possible problems, I will answer later after I know the situation)

May 17, 2018
15:10, EEST
Avatar
hbrackel
Member
Members
Forum Posts: 144
Member Since:
February 21, 2014
sp_UserOfflineSmall Offline

Hi Bjarne,

my setup is of the kind
ObjectTypeA has an optional node ObjectB of ObjectTypeB
ObjectTypeB has an optional variable “VariableInB” of BaseDataVariableType

val conf = TypeDefinitionBasedNodeBuilderConfiguration.builder()
conf.addOptional(
UaBrowsePath.from(SdkTestIds.ObjectTypeB, UaRelativePath.from(UaQualifiedName.from(testNamespaceUri, "VariableInB"))),
UaBrowsePath.from(SdkTestIds.ObjectTypeA, UaRelativePath.from(UaQualifiedName.from(testNamespaceUri, "ObjectB")))
)
testNodeManager.nodeBuilderConfiguration = conf.build()
val objA = testNodeManager.createInstance(ObjectTypeANode::class.java, "ObjectA", nodeId)

The Kotlin code above creates an ObjectA instance containing an ObjectB, but the ObjectB does not contain the VariableInB. I also tried a relativeBrowsePath including both ObjectB as well as VariableInB, different ordering, as well as setinstantiateAllOptionals=true. Another attempt to use a nodeBuilder specific configuration gave the same result. It also doesn’t make a difference, whether the browse paths are in a single addOptional() or individual addOptional() calls.

Could you eventually provide a little code snippet which demonstrates the “best practices” of creating hierarchical optional node structures (if the above is not how it should be done)?

Thanks,
Hans-Uwe

May 17, 2018
18:05, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

That should be correct (but I can doublecheck tomorrow, also sorry if this post is a bit messy, as the subject is not that trivial.. I should really write a blog post / better tutorial..).

The thing I pointed out with the “2 different ways” is that what is the actual node structure in the Types part of the address space, is it option 1 or 2? i.e. (a bit simplified, but should work in this case), is it possible to find a node “VariableInB” by starting from the ObjectTypeA node and (ONLY) going forward (I guess HasComponent) references? If yes, then it is option 1, if not it is 2. Since you still have the problem I would assume it is 2 (which does not work directly out-of-the-box).

The instantiation system / NodeBuilder uses the Types address space nodes when instantiating and normally it can only instantiate InstanceDeclrations that are found when looking at a Type node (+all supertypes) and it’s forward hierarchical references (the exact logic is based on the specification, v1.03 Part 3, section 6.4.2 “Creating an Instance”) . It does not look at the TypeDefinition of the InstanceDeclrations, which is why in the case of 2 when making the InstanceDeclarationHierarchy of ObjectTypeA it does not contain InstanceDeclaration for “VariableInB”.

There is a second “test”/workaround that also could be tried. Call InstanceDeclarationHierarchy.addInstanceDeclarationsTypeDefinitionOptionals = true (it is static public field) at the start of main (or before SDK interactions), does it work then? (if yes, then it is option 2). Note that it is experimental, not very well tested and causes problems if the same InstanceDeclaration node is found multiple times (NodeBuilder creates one instance node per InstanceDeclaration node) and also in theory can lead to infinite address space / out of memory if a complex optional node structure can lead to itself (e.g. linkedlist “node” style type could have infite chain instances of itself as optional).

IF the result of this was that the option 2 was true, then I recommend transforming the nodeset so that it becomes 1. If you are using UaModeler, you should be able to do this via selecting the optional ObjectB node in ObjectTypeA in the Information Model left down panel, then click on the “Select optional components” button below the Object section in the middle of the program, and select the “VariableInB”, then export the model and then it should work without the InstanceDeclarationHierarchy.addInstanceDeclarationsTypeDefinitionOptionals = true

May 17, 2018
18:57, EEST
Avatar
hbrackel
Member
Members
Forum Posts: 144
Member Since:
February 21, 2014
sp_UserOfflineSmall Offline

Hi,

the nodeBuilder approach is very handy for straight forward tasks and in particular provides “BrowseName”-safety. As I will have to do more “nasty” things with the instances, such as updating (remove, change value, add) their optional components based on business object states, I’m now considering injecting the business objects into the Generated implementation classes and creating the optional components manually in the afterCreate() method. I guess that the effort is not much different compared to the “per node” creation of a NodeBuilderConfiguration.

I would have another related question: looking at the generated code, there is a static method setObjectxxxxeInitializer(…). Is this meant to be used by custom code or by a NodeBuilder?

Thanks,
Hans-Uwe

May 18, 2018
13:17, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1026
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

Well there is a small semantical difference, if you make sub-nodes yourself from a TypeDefinition vs. instantiating it as part normal instatiation. Making the node yourself ignores possible overrides made to the InstanceDeclarations in the type. If you do not have overrides, then it should be semantically the same. Of course you can also modify the nodes after you have made them yourself so that they are identical. Overriding is explained in the spec v1.03, Part 3, section 6.3.3.3 “Overriding InstanceDeclarations”.

Using your setup as an example, the InstanceDeclaration found for path ObjectTypeA/ObjectB/VariableInB can/could contain overrides to the node “VariableInB” found via path ObjectTypeB/VariableInB. If you instantiate ObjectTypeB yourself and put it to ObjectTypeAInstance/ObjectB, then the node ObjectTypeAInstance/ObjectB/VariableInB is from the definition of ObjectTypeB, not from the ObjectTypeA. However this does not matter, if the node ObjectTypeA/ObjectB/VariableInB does not exist, or is identical to the node ObjectTypeB/VariableInB.

The static setXXXInitializer is intended to be an alternative way vs. editing the generated XXXTypeNode classes manually. See the code in XXXTypeNodeBase, if there is an implementation set, it will be called in the afterCreate method of the XXXTypeNodeBase. The same kind of logic is provided for making Method implementations, via the static setXXXMethodImplementation methods.

Forum Timezone: Europe/Helsinki

Most Users Ever Online: 1919

Currently Online:
14 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

Heikki Tahvanainen: 402

hbrackel: 144

rocket science: 88

pramanj: 86

Francesco Zambon: 83

Ibrahim: 78

Sabari: 62

kapsl: 57

gjevremovic: 49

Xavier: 43

Member Stats:

Guest Posters: 0

Members: 737

Moderators: 7

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1524

Posts: 6450

Newest Members:

fannielima, kristiewinkle8, rust, christamcdowall, redaahern07571, nigelbdhmp, travistimmons, AnnelCib, dalenegettinger, howardkennerley

Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1026, Jimmy Ni: 26, Matti Siponen: 346, Lusetti: 0

Administrators: admin: 1