From b1378d2845c317322aa673f322d6b6e13cd92c11 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Thu, 18 May 2023 18:12:12 +0200 Subject: [PATCH] DataContainerChild is identified by NodeIdentifier 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 --- .../yang/data/api/schema/ChoiceNode.java | 5 --- .../yang/data/api/schema/ContainerNode.java | 5 --- .../data/api/schema/DataContainerChild.java | 5 ++- .../data/api/schema/DataContainerNode.java | 4 +-- .../yang/data/api/schema/ForeignDataNode.java | 4 --- .../yang/data/api/schema/LeafNode.java | 5 --- .../yang/data/api/schema/LeafSetNode.java | 4 --- .../yang/data/api/schema/MapNode.java | 4 --- .../yang/data/api/schema/NormalizedNodes.java | 16 +++++---- .../data/api/schema/NormalizedNodesTest.java | 12 ++----- ...ractImmutableDataContainerNodeBuilder.java | 22 ++++++------ .../AbstractImmutableDataContainerNode.java | 3 +- .../data/tree/leafref/LeafRefValidation.java | 34 +++++++++---------- 13 files changed, 48 insertions(+), 75 deletions(-) diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ChoiceNode.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ChoiceNode.java index 17a893fa53..721d0ed7ca 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ChoiceNode.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ChoiceNode.java @@ -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 choice. * @@ -30,7 +28,4 @@ public interface ChoiceNode extends MixinNode, DataContainerNode, DataContainerC default Class contract() { return ChoiceNode.class; } - - @Override - NodeIdentifier getIdentifier(); } diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ContainerNode.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ContainerNode.java index ebabb2c2d9..56570b227e 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ContainerNode.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ContainerNode.java @@ -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 contract() { return ContainerNode.class; } - - @Override - NodeIdentifier getIdentifier(); } diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerChild.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerChild.java index ac5565fe2c..26bc389a4b 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerChild.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerChild.java @@ -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; * */ public interface DataContainerChild extends NormalizedNode { - + @Override + NodeIdentifier getIdentifier(); } diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerNode.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerNode.java index 6fc60cffc9..df50de51db 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerNode.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerNode.java @@ -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 * */ public interface DataContainerNode - extends DistinctNodeContainer, OrderingAware.System { + extends DistinctNodeContainer, OrderingAware.System { @Override int hashCode(); diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ForeignDataNode.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ForeignDataNode.java index 30331ff015..10a47328c6 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ForeignDataNode.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ForeignDataNode.java @@ -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 extends DataContainerChild permits AnydataNode, AnyxmlNode { - @Override - NodeIdentifier getIdentifier(); - /** * {@inheritDoc} * diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafNode.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafNode.java index e320e04584..7b01181d66 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafNode.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafNode.java @@ -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 extends ValueNode, DataContainerChild default Class contract() { return LeafNode.class; } - - @Override - NodeIdentifier getIdentifier(); } diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafSetNode.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafSetNode.java index bfb2c76c36..2b0c3882c2 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafSetNode.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafSetNode.java @@ -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 @Override @SuppressWarnings("rawtypes") Class contract(); - - @Override - NodeIdentifier getIdentifier(); } diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/MapNode.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/MapNode.java index 14da9ef15f..782b508c18 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/MapNode.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/MapNode.java @@ -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 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. diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodes.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodes.java index 82b2611262..903c77af0e 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodes.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodes.java @@ -98,18 +98,20 @@ public final class NormalizedNodes { requireNonNull(path, "Path must not be null").getPathArguments()); } - @SuppressWarnings({ "unchecked", "rawtypes" }) public static Optional 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); } /** diff --git a/data/yang-data-api/src/test/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodesTest.java b/data/yang-data-api/src/test/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodesTest.java index 4416aaf92b..f1253cd5b1 100644 --- a/data/yang-data-api/src/test/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodesTest.java +++ b/data/yang-data-api/src/test/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodesTest.java @@ -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"); diff --git a/data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java b/data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java index a861ea4066..8a294ab454 100644 --- a/data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java +++ b/data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java @@ -55,29 +55,31 @@ abstract class AbstractImmutableDataContainerNodeBuilder= 0) { - this.value = newHashMap(sizeHint); + value = newHashMap(sizeHint); } else { - this.value = newHashMap(); + value = newHashMap(); } - this.dirty = false; + dirty = false; + nodeIdentifier = null; } AbstractImmutableDataContainerNodeBuilder(final AbstractImmutableDataContainerNode 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 withoutChild(final PathArgument key) { checkDirty(); - this.value.remove(key); + value.remove(key); return this; } @Override public DataContainerNodeBuilder withNodeIdentifier(final I withNodeIdentifier) { - this.nodeIdentifier = withNodeIdentifier; + nodeIdentifier = withNodeIdentifier; return this; } diff --git a/data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java b/data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java index fa8e37ff0d..c3b0aeb479 100644 --- a/data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java +++ b/data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java @@ -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) { - 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 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 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 values, final DataContainerNode parent, - final PathArgument arg, final List nodePredicates, final Deque path, + final NodeIdentifier arg, final List nodePredicates, final Deque 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 createMapEntryPredicate(final List nodePredicates, final YangInstanceIdentifier current) { - final Map> keyValues = new HashMap<>(); - for (QNamePredicate predicate : nodePredicates) { + final var keyValues = new HashMap>(); + for (var predicate : nodePredicates) { keyValues.put(predicate.getIdentifier(), getPathKeyExpressionValues(predicate.getPathKeyExpression(), current)); } return mapEntry -> { - for (final Entry 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 values, final NormalizedNode node, + private void addNextValues(final Set values, final DataContainerChild node, final List nodePredicates, final Deque 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 path = createPath(predicatePathKeyExpression); + final var path = createPath(predicatePathKeyExpression); path.pollFirst(); return computeValues(parent, path, null); }).orElse(ImmutableSet.of()); -- 2.36.6