Skip to content

Commit 7e025a1

Browse files
committed
fix assigning of multiple dyn nodes
1 parent 84e59fa commit 7e025a1

File tree

6 files changed

+61
-12
lines changed

6 files changed

+61
-12
lines changed

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Add necessary dependencies:
1616
<dependency>
1717
<groupId>com.connectedcooking.opcua</groupId>
1818
<artifactId>opcua-dynamic-node-manager</artifactId>
19-
<version>0.1.2</version>
19+
<version>0.1.3</version>
2020
</dependency>
2121
<dependency>
2222
<groupId>com.prosysopc.ua</groupId>
@@ -329,6 +329,13 @@ There are basic micrometer.io metrics included:
329329
330330
## Release Notes
331331
332+
**0.1.3**
333+
- Fix assigning of multiple dynamic nodes
334+
335+
**0.1.2**
336+
- Map `UtcTime` for `ZonedDateTime` implicitly
337+
- Add a new ctor to `RealNodeId`
338+
332339
**0.1.1**
333340
- Update to Prosys 4.10.0-58
334341

examples/parent/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<dependency>
2828
<groupId>com.connectedcooking.opcua</groupId>
2929
<artifactId>opcua-dynamic-node-manager</artifactId>
30-
<version>0.1.2-SNAPSHOT</version>
30+
<version>0.1.3-SNAPSHOT</version>
3131
</dependency>
3232
<dependency>
3333
<groupId>com.prosysopc.ua</groupId>

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.connectedcooking.opcua</groupId>
66
<artifactId>opcua-dynamic-node-manager</artifactId>
7-
<version>0.1.2-SNAPSHOT</version>
7+
<version>0.1.3-SNAPSHOT</version>
88

99
<name>OPC UA Dynamic Node Manager</name>
1010
<description>Java library for implementing a dynamic node manager that responses dynamically based on the user context.</description>

src/main/java/com/connectedcooking/opcua/dynamicnodemanager/core/DynNodeManager.java

+14-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class DynNodeManager {
1212

1313
protected final List<DynNode> nodes = new LinkedList<>();
1414

15-
protected final Map<RealNodeId, AssignedChild> assignedChildren = new HashMap<>();
15+
protected final Map<RealNodeId, Set<AssignedChild>> assignedChildren = new HashMap<>();
1616
protected final Map<DynNodeId, DynRequest.Full<Boolean>> canBrowse = new HashMap<>();
1717

1818
/**
@@ -104,12 +104,15 @@ public void assign(RealNodeId parentId, DynNodeId childNodeId, RealNodeId childR
104104
* See {@link #assign(RealNodeId, DynNodeId, BiFunction)}
105105
*/
106106
public void assignSet(RealNodeId parentId, DynNodeId nodeId, BiFunction<UserContext, DynNodeId, Collection<RealNodeId>> fn) {
107-
assignedChildren.compute(parentId, (k, fns) -> {
108-
if (fns == null) {
109-
fns = new AssignedChild(nodeId);
107+
assignedChildren.compute(parentId, (k, children) -> {
108+
if (children == null) {
109+
children = new HashSet<>();
110110
}
111-
fns.fns.add(fn);
112-
return fns;
111+
var child = new AssignedChild(nodeId);
112+
child.fns.add(fn);
113+
114+
children.add(child);
115+
return children;
113116
});
114117
}
115118

@@ -125,8 +128,11 @@ public List<DynReference> assignedChildren(RealNodeId parentId, UserContext user
125128
if (assignedChildren != null) {
126129
var assigned = assignedChildren.get(parentId);
127130
if (assigned != null) {
128-
assigned.fns.forEach(fn -> fn.apply(userContext, assigned.childNodeId)
129-
.forEach(rid -> references.add(new DynReference.HasComponentRef(parentId, rid))));
131+
for (var child: assigned) {
132+
child.fns.forEach(fn ->
133+
fn.apply(userContext, child.childNodeId).forEach(rid ->
134+
references.add(new DynReference.HasComponentRef(parentId, rid))));
135+
}
130136
}
131137
}
132138
return Collections.unmodifiableList(references);

src/main/java/com/connectedcooking/opcua/dynamicnodemanager/core/RealNodeId.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public RealNodeId(String parent, String child) {
5151
* @param child the child real node ID
5252
*/
5353
public RealNodeId(RealNodeId parent, RealNodeId child) {
54-
this(parent.namespaceIndex, parent.identifier + "/" + child.identifier);
54+
this(parent.namespaceIndex != null ? parent.namespaceIndex : -1, parent.identifier + "/" + child.identifier);
5555
}
5656

5757
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.connectedcooking.opcua.dynamicnodemanager.core;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.junit.jupiter.api.extension.ExtendWith;
5+
import org.mockito.junit.jupiter.MockitoExtension;
6+
7+
import java.util.List;
8+
import java.util.stream.Collectors;
9+
10+
import static org.assertj.core.api.Assertions.assertThat;
11+
12+
@ExtendWith(MockitoExtension.class)
13+
class DynNodeManagerTest {
14+
15+
@Test
16+
void multipleAssignedChildrenSet() {
17+
var parent = new RealNodeId("Parent");
18+
var dynNode1 = new DynNodeId("DynNodeA_<No.>");
19+
var dynNode2 = new DynNodeId("DynNodeB_<No.>");
20+
21+
var dnm = new DynNodeManager();
22+
23+
dnm.assignSet(parent, dynNode1, (ctx, nodeId) -> List.of(
24+
new RealNodeId("DynNodeA_1")));
25+
26+
dnm.assignSet(parent, dynNode2, (ctx, nodeId) -> List.of(
27+
new RealNodeId("DynNodeB_1"), new RealNodeId("DynNodeB_2")));
28+
29+
var references = dnm.assignedChildren(parent, null).stream()
30+
.map(DynReference::targetId)
31+
.map(RealNodeId::identifier)
32+
.collect(Collectors.toList());
33+
34+
assertThat(references).containsExactlyInAnyOrder("DynNodeA_1", "DynNodeB_1", "DynNodeB_2");
35+
}
36+
}

0 commit comments

Comments
 (0)