Fix ChoiceNodeContextNode's byQName indexing 27/100227/2
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 23 Mar 2022 17:31:39 +0000 (18:31 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 23 Mar 2022 17:46:01 +0000 (18:46 +0100)
When we are traversing by provided QName, we are meant to encounter
each ContextNode significant to PathArgument construction. This works
for all cases except for 'choice->case->choice', where
ChoiceNodeContextNode's internal indexing does not account for itself:
it ends up storing the second ChoiceNodeContextNode under the
ChoiceSchemaNode's QName -- and therefore it fails to find it by its
consituents' QNames.

This has impact primarily on instance-identifier parsers, as evidenced
by the corresponding JSON-based unit test.

Fix this by properly overriding getQNameIdentifiers() to provide the
internal table's keySet().

JIRA: YANGTOOLS-1411
Change-Id: I11df2d4072157e06342c2899dbcf02f74eef8090
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractComplexJsonTest.java
codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/YT1411Test.java [new file with mode: 0644]
data/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/ChoiceNodeContextNode.java

index a8815f56ff5e81e016b06315f61a9b5c433d776b..c68033032aa021b9dd5e010cd39db64a1c149208 100644 (file)
@@ -20,10 +20,12 @@ import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
 public abstract class AbstractComplexJsonTest {
     static final QName CONT_1 = QName.create("ns:complex:json", "2014-08-11", "cont1");
+    static final NodeIdentifier CONT_1_NODEID = new NodeIdentifier(CONT_1);
+
     private static final QName EMPTY_LEAF = QName.create(CONT_1, "empty");
 
     static final ContainerNode CONT1_WITH_EMPTYLEAF = Builders.containerBuilder()
-            .withNodeIdentifier(new NodeIdentifier(CONT_1))
+            .withNodeIdentifier(CONT_1_NODEID)
             .addChild(ImmutableNodes.leafNode(EMPTY_LEAF, Empty.value()))
             .build();
 
diff --git a/codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/YT1411Test.java b/codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/YT1411Test.java
new file mode 100644 (file)
index 0000000..6e37b34
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.codec.gson;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.google.gson.stream.JsonReader;
+import java.io.StringReader;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+
+public class YT1411Test extends AbstractComplexJsonTest {
+    @Test
+    public void testChoiceCaseChoiceIdentifier() {
+        final var result = new NormalizedNodeResult();
+        final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+        final var jsonParser = JsonParserStream.create(streamWriter,
+            JSONCodecFactorySupplier.RFC7951.getShared(schemaContext));
+        jsonParser.parse(new JsonReader(new StringReader("{\n"
+            + "  \"complexjson:cont1\": {\n"
+            + "    \"lst11\": [\n"
+            + "      {\n"
+            + "        \"key111\": \"foo\",\n"
+            + "        \"lf111\": \"bar\",\n"
+            + "        \"lf112\": \"/complexjson:cont1/case11-choice-case-container\"\n"
+            + "      }\n"
+            + "    ]\n"
+            + "  }\n"
+            + "}")));
+        final var cont1 = result.getResult();
+        assertThat(cont1, instanceOf(ContainerNode.class));
+
+        final QName lst11 = QName.create(CONT_1, "lst11");
+        final var lf112 = NormalizedNodes.findNode(cont1,
+            new NodeIdentifier(lst11),
+            NodeIdentifierWithPredicates.of(lst11,
+                Map.of(QName.create(CONT_1, "key111"), "foo", QName.create(CONT_1, "lf111"), "bar")),
+            new NodeIdentifier(QName.create(CONT_1, "lf112")))
+            .orElseThrow();
+        assertThat(lf112, instanceOf(LeafNode.class));
+
+        final QName augmentChoice1 = QName.create(CONT_1, "augment-choice1");
+        assertEquals(YangInstanceIdentifier.create(
+            CONT_1_NODEID,
+            AugmentationIdentifier.create(Set.of(augmentChoice1)),
+            new NodeIdentifier(augmentChoice1),
+            new NodeIdentifier(QName.create(CONT_1, "augment-choice2")),
+            new NodeIdentifier(QName.create(CONT_1, "case11-choice-case-container"))),
+            ((LeafNode<?>) lf112).body());
+    }
+}
index 7cd43d7b814de6b7aabf7d8667cac708c6353611..a93d1f1883b8b3900dea5fe6351b434687ae3517 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.data.util;
 
 import com.google.common.collect.ImmutableMap;
+import java.util.Set;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
@@ -46,4 +47,9 @@ final class ChoiceNodeContextNode extends AbstractMixinContextNode<NodeIdentifie
     public DataSchemaContextNode<?> getChild(final QName child) {
         return byQName.get(child);
     }
+
+    @Override
+    protected Set<QName> getQNameIdentifiers() {
+        return byQName.keySet();
+    }
 }