DataContainerChild is identified by NodeIdentifier 42/106042/2
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 18 May 2023 16:12:12 +0000 (18:12 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 18 May 2023 16:38:58 +0000 (18:38 +0200)
With AugmentationNode/MountPointNode gone, it is clear that all
DataContainerChild interfaces are identified by NodeIdentifier. Codify
that in DataContainerChild and adjust DataContainerNode specialization
accordingly.

JIRA: YANGTOOLS-1511
Change-Id: Ide80a1e84cf7851f94fe5d71c43865922bb9d9ad
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
13 files changed:
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ChoiceNode.java
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ContainerNode.java
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerChild.java
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerNode.java
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ForeignDataNode.java
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafNode.java
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafSetNode.java
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/MapNode.java
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodes.java
data/yang-data-api/src/test/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodesTest.java
data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java
data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java
data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/leafref/LeafRefValidation.java

index 17a893fa537e8e98c3072d16cef2cd89c5ac4553..721d0ed7cafdbac10643ca282a5cd464c4e0cadf 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-
 /**
  * Node representing data instance of <code>choice</code>.
  *
@@ -30,7 +28,4 @@ public interface ChoiceNode extends MixinNode, DataContainerNode, DataContainerC
     default Class<ChoiceNode> contract() {
         return ChoiceNode.class;
     }
-
-    @Override
-    NodeIdentifier getIdentifier();
 }
index ebabb2c2d95e900340fc186af3535cf08fe4f301..56570b227e8f0edfd7b34a58269bdb50d5546695 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-
 /**
  * Data subtree with cardinality 0..1 in the context of parent node.
  *
@@ -24,7 +22,4 @@ public interface ContainerNode extends DataContainerNode, DataContainerChild {
     default Class<ContainerNode> contract() {
         return ContainerNode.class;
     }
-
-    @Override
-    NodeIdentifier getIdentifier();
 }
index ac5565fe2c00ed725a1f740846704cfdb6361337..26bc389a4b68732266fc07e7df3674c459cdf90a 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+
 /**
  * Marker interface for direct children of {@link DataContainerNode}.
  *
@@ -24,5 +26,6 @@ package org.opendaylight.yangtools.yang.data.api.schema;
  * </ul>
  */
 public interface DataContainerChild extends NormalizedNode {
-
+    @Override
+    NodeIdentifier getIdentifier();
 }
index 6fc60cffc9b6d6b28963948abd1360ffeadc4020..df50de51db135a49e85eb4654fdbc4999cc19a29 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 
 /**
  * Abstract node which does not have value but contains valid {@link DataContainerChild} nodes. Schema of this node is
@@ -27,7 +27,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum
  * </ul>
  */
 public interface DataContainerNode
-        extends DistinctNodeContainer<PathArgument, DataContainerChild>, OrderingAware.System {
+        extends DistinctNodeContainer<NodeIdentifier, DataContainerChild>, OrderingAware.System {
     @Override
     int hashCode();
 
index 30331ff015f49dfaca89acab593bcd013e99f8bb..10a47328c6f6318d0d42de6e0156fec1742592a1 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.yangtools.yang.data.api.schema;
 import com.google.common.annotations.Beta;
 import javax.xml.transform.dom.DOMSource;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 
 /**
  * A NormalizedNode holding a value in some foreign object model. The object model is identified by a single class,
@@ -24,9 +23,6 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
  */
 @Beta
 public sealed interface ForeignDataNode<V> extends DataContainerChild permits AnydataNode, AnyxmlNode {
-    @Override
-    NodeIdentifier getIdentifier();
-
     /**
      * {@inheritDoc}
      *
index e320e04584453e2ef36f3969fb6cef4de8d05272..7b01181d6625f3896c3f4346fb2294876afa9fea 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-
 /**
  * Leaf node with multiplicity 0..1.
  *
@@ -24,7 +22,4 @@ public non-sealed interface LeafNode<T> extends ValueNode<T>, DataContainerChild
     default Class<LeafNode> contract() {
         return LeafNode.class;
     }
-
-    @Override
-    NodeIdentifier getIdentifier();
 }
index bfb2c76c362b6f7504792b3d2dcdbaa45a1e265e..2b0c3882c245157bb2c543adbe2814a35b990c4f 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 
 /**
@@ -25,7 +24,4 @@ public sealed interface LeafSetNode<T>
     @Override
     @SuppressWarnings("rawtypes")
     Class<? extends LeafSetNode> contract();
-
-    @Override
-    NodeIdentifier getIdentifier();
 }
index 14da9ef15fadcaddb69c11f9465770f59b133165..782b508c18ba427ad604aad3861054700f375668 100644 (file)
@@ -11,7 +11,6 @@ import com.google.common.annotations.Beta;
 import java.util.Collection;
 import java.util.Map;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 
 /**
@@ -27,9 +26,6 @@ public sealed interface MapNode
     @Override
     Class<? extends MapNode> contract();
 
-    @Override
-    NodeIdentifier getIdentifier();
-
     /**
      * Return a {@link Map} view of this node. Note that the iteration order of the returned is map is not defined in
      * this interface.
index 82b26112621548615c4772b18afc947fb13f2d9e..903c77af0e8163e50639611936ec93740b0f2b27 100644 (file)
@@ -98,18 +98,20 @@ public final class NormalizedNodes {
             requireNonNull(path, "Path must not be null").getPathArguments());
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
     public static Optional<NormalizedNode> getDirectChild(final NormalizedNode node,
             final PathArgument pathArg) {
-        if (node instanceof DataContainerNode dataContainer) {
-            return (Optional) dataContainer.findChildByArg(pathArg);
+        final NormalizedNode child;
+        if (node instanceof DataContainerNode dataContainer && pathArg instanceof NodeIdentifier nid) {
+            child = dataContainer.childByArg(nid);
         } else if (node instanceof MapNode map && pathArg instanceof NodeIdentifierWithPredicates nip) {
-            return (Optional) map.findChildByArg(nip);
+            child = map.childByArg(nip);
         } else if (node instanceof LeafSetNode<?> leafSet && pathArg instanceof NodeWithValue<?> nwv) {
-            return (Optional) leafSet.findChildByArg(nwv);
+            child = leafSet.childByArg(nwv);
+        } else {
+            // Anything else, including ValueNode
+            child = null;
         }
-        // Anything else, including ValueNode
-        return Optional.empty();
+        return Optional.ofNullable(child);
     }
 
     /**
index 4416aaf92b2a0a26227445f5001523dafe63c53d..f1253cd5b17116582cc5846967031c0749668e52 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.yangtools.yang.data.api.schema;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
@@ -40,8 +39,7 @@ public class NormalizedNodesTest {
 
         final var mockedDataContainerNode = mock(DataContainerNode.class);
         final var mockedContainerNode = mock(ContainerNode.class);
-        doReturn(mockedContainerNode).when(mockedDataContainerNode).childByArg(any(PathArgument.class));
-        doCallRealMethod().when(mockedDataContainerNode).findChildByArg(any(PathArgument.class));
+        doReturn(mockedContainerNode).when(mockedDataContainerNode).childByArg(any());
 
         assertEquals(Optional.of(mockedContainerNode),
             NormalizedNodes.getDirectChild(mockedDataContainerNode, mockedPathArgument));
@@ -52,7 +50,6 @@ public class NormalizedNodesTest {
         final var nodeIdentifierWithPredicates = NodeIdentifierWithPredicates.of(listQName, listKeyQName, "str-value");
         final var mockedMapEntryNode = mock(MapEntryNode.class);
         doReturn(mockedMapEntryNode).when(mockedMapNode).childByArg(any(NodeIdentifierWithPredicates.class));
-        doCallRealMethod().when(mockedMapNode).findChildByArg(any(NodeIdentifierWithPredicates.class));
 
         assertEquals(Optional.of(mockedMapEntryNode),
             NormalizedNodes.getDirectChild(mockedMapNode, nodeIdentifierWithPredicates));
@@ -62,7 +59,6 @@ public class NormalizedNodesTest {
         final QName leafListQName = QName.create("test-ns", "test-leaf-list");
         final NodeWithValue<?> nodeWithValue = new NodeWithValue<>(leafListQName, "str-value");
         doReturn(mockedLeafSetEntryNode).when(mockedLeafSetNode).childByArg(any(NodeWithValue.class));
-        doCallRealMethod().when(mockedLeafSetNode).findChildByArg(any(NodeWithValue.class));
         assertEquals(Optional.of(mockedLeafSetEntryNode),
             NormalizedNodes.getDirectChild(mockedLeafSetNode, nodeWithValue));
     }
@@ -72,10 +68,8 @@ public class NormalizedNodesTest {
         final DataContainerNode mockedDataContainerNode = mock(DataContainerNode.class);
         final ContainerNode mockedContainerNode = mock(ContainerNode.class);
         final LeafNode<?> mockedLeafNode = mock(LeafNode.class);
-        doReturn(mockedContainerNode).when(mockedDataContainerNode).childByArg(any(PathArgument.class));
-        doCallRealMethod().when(mockedDataContainerNode).findChildByArg(any(PathArgument.class));
-        doReturn(mockedLeafNode).when(mockedContainerNode).childByArg(any(PathArgument.class));
-        doCallRealMethod().when(mockedContainerNode).findChildByArg(any(PathArgument.class));
+        doReturn(mockedContainerNode).when(mockedDataContainerNode).childByArg(any());
+        doReturn(mockedLeafNode).when(mockedContainerNode).childByArg(any());
 
         final QName node1QName = QName.create("test-ns", "2016-09-16", "node1");
         final QName node2Qname = QName.create("test-ns", "2016-09-16", "node2");
index a861ea4066282a68ab43ae3626326deb9a2c18bd..8a294ab454ff2f06f15a4487af798a48761c3dbb 100644 (file)
@@ -55,29 +55,31 @@ abstract class AbstractImmutableDataContainerNodeBuilder<I extends PathArgument,
     private boolean dirty;
 
     AbstractImmutableDataContainerNodeBuilder() {
-        this.value = newHashMap();
-        this.dirty = false;
+        value = newHashMap();
+        dirty = false;
+        nodeIdentifier = null;
     }
 
     AbstractImmutableDataContainerNodeBuilder(final int sizeHint) {
         if (sizeHint >= 0) {
-            this.value = newHashMap(sizeHint);
+            value = newHashMap(sizeHint);
         } else {
-            this.value = newHashMap();
+            value = newHashMap();
         }
-        this.dirty = false;
+        dirty = false;
+        nodeIdentifier = null;
     }
 
     AbstractImmutableDataContainerNodeBuilder(final AbstractImmutableDataContainerNode<I, R> node) {
-        this.nodeIdentifier = node.getIdentifier();
+        nodeIdentifier = node.getIdentifier();
 
         /*
          * This quite awkward. What we actually want to be saying here is: give me a copy-on-write view of your
          * children. The API involved in that could be a bit hairy, so we do the next best thing and rely on the fact
          * that the returned object implements a specific interface, which leaks the functionality we need.
          */
-        this.value = node.getChildren();
-        this.dirty = true;
+        value = node.getChildren();
+        dirty = true;
     }
 
     protected final I getNodeIdentifier() {
@@ -129,13 +131,13 @@ abstract class AbstractImmutableDataContainerNodeBuilder<I extends PathArgument,
     @Override
     public DataContainerNodeBuilder<I, R> withoutChild(final PathArgument key) {
         checkDirty();
-        this.value.remove(key);
+        value.remove(key);
         return this;
     }
 
     @Override
     public DataContainerNodeBuilder<I, R> withNodeIdentifier(final I withNodeIdentifier) {
-        this.nodeIdentifier = withNodeIdentifier;
+        nodeIdentifier = withNodeIdentifier;
         return this;
     }
 
index fa8e37ff0d075a0635eca0fecf67670d668c6dc6..c3b0aeb47986f9da97f4c8cea30aaa5450afa217 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
 import java.util.Collection;
 import java.util.Map;
 import org.opendaylight.yangtools.util.ImmutableOffsetMap;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
@@ -25,7 +26,7 @@ public abstract class AbstractImmutableDataContainerNode<K extends PathArgument,
     }
 
     @Override
-    public final DataContainerChild childByArg(final PathArgument child) {
+    public final DataContainerChild childByArg(final NodeIdentifier child) {
         return LazyLeafOperations.getChild(children, child);
     }
 
index 757ac3d55973eedaaa6193d11d2b18a1f8701aa6..be6f05873aebcb30872bec058d34b641dbff4819 100644 (file)
@@ -17,8 +17,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
@@ -347,8 +345,8 @@ public final class LeafRefValidation {
             values.add(node.body());
             return;
         }
-        if (node instanceof LeafSetNode<?>) {
-            for (final NormalizedNode entry : ((LeafSetNode<?>) node).body()) {
+        if (node instanceof LeafSetNode<?> leafSet) {
+            for (var entry : leafSet.body()) {
                 values.add(entry.body());
             }
             return;
@@ -359,11 +357,11 @@ public final class LeafRefValidation {
             return;
         }
 
-        final PathArgument pathArgument = new NodeIdentifier(next.getQName());
-        if (node instanceof DataContainerNode) {
-            processChildNode(values, (DataContainerNode) node, pathArgument, next.getQNamePredicates(), path, current);
-        } else if (node instanceof MapNode) {
-            Stream<MapEntryNode> entries = ((MapNode) node).body().stream();
+        final var pathArgument = new NodeIdentifier(next.getQName());
+        if (node instanceof DataContainerNode dataContainer) {
+            processChildNode(values, dataContainer, pathArgument, next.getQNamePredicates(), path, current);
+        } else if (node instanceof MapNode map) {
+            Stream<MapEntryNode> entries = map.body().stream();
             if (!nodePredicates.isEmpty() && current != null) {
                 entries = entries.filter(createMapEntryPredicate(nodePredicates, current));
             }
@@ -374,15 +372,15 @@ public final class LeafRefValidation {
     }
 
     private void processChildNode(final Set<Object> values, final DataContainerNode parent,
-            final PathArgument arg, final List<QNamePredicate> nodePredicates, final Deque<QNameWithPredicate> path,
+            final NodeIdentifier arg, final List<QNamePredicate> nodePredicates, final Deque<QNameWithPredicate> path,
             final YangInstanceIdentifier current) {
-        final DataContainerChild child = parent.childByArg(arg);
+        final var child = parent.childByArg(arg);
         if (child == null) {
             // FIXME: YANGTOOLS-901. We have SchemaContext nearby, hence we should be able to cache how to get
             //        to the leaf with with specified QName, without having to iterate through Choices.
             //        That perhaps means we should not have QNameWithPredicates, but NodeIdentifierWithPredicates as
             //        the path specification.
-            for (final DataContainerChild mixin : parent.body()) {
+            for (var mixin : parent.body()) {
                 if (mixin instanceof ChoiceNode) {
                     addValues(values, mixin, nodePredicates, path, current);
                 }
@@ -394,15 +392,15 @@ public final class LeafRefValidation {
 
     private Predicate<MapEntryNode> createMapEntryPredicate(final List<QNamePredicate> nodePredicates,
             final YangInstanceIdentifier current) {
-        final Map<QName, Set<?>> keyValues = new HashMap<>();
-        for (QNamePredicate predicate : nodePredicates) {
+        final var keyValues = new HashMap<QName, Set<?>>();
+        for (var predicate : nodePredicates) {
             keyValues.put(predicate.getIdentifier(), getPathKeyExpressionValues(predicate.getPathKeyExpression(),
                 current));
         }
 
         return mapEntry -> {
-            for (final Entry<QName, Object> entryKeyValue : mapEntry.getIdentifier().entrySet()) {
-                final Set<?> allowedValues = keyValues.get(entryKeyValue.getKey());
+            for (var entryKeyValue : mapEntry.getIdentifier().entrySet()) {
+                final var allowedValues = keyValues.get(entryKeyValue.getKey());
                 if (allowedValues != null && !allowedValues.contains(entryKeyValue.getValue())) {
                     return false;
                 }
@@ -411,7 +409,7 @@ public final class LeafRefValidation {
         };
     }
 
-    private void addNextValues(final Set<Object> values, final NormalizedNode node,
+    private void addNextValues(final Set<Object> values, final DataContainerChild node,
             final List<QNamePredicate> nodePredicates, final Deque<QNameWithPredicate> path,
             final YangInstanceIdentifier current) {
         final QNameWithPredicate element = path.pop();
@@ -425,7 +423,7 @@ public final class LeafRefValidation {
     private Set<?> getPathKeyExpressionValues(final LeafRefPath predicatePathKeyExpression,
             final YangInstanceIdentifier current) {
         return findParentNode(Optional.of(root), current).map(parent -> {
-            final Deque<QNameWithPredicate> path = createPath(predicatePathKeyExpression);
+            final var path = createPath(predicatePathKeyExpression);
             path.pollFirst();
             return computeValues(parent, path, null);
         }).orElse(ImmutableSet.of());