Fix anyxml-to-JSON translation duplication error 44/96944/9
authorManoj Chokka <cmanoj8@gmail.com>
Tue, 20 Jul 2021 12:38:00 +0000 (12:38 +0000)
committerRobert Varga <nite@hq.sk>
Tue, 1 Nov 2022 15:46:39 +0000 (15:46 +0000)
JSONNormalizedNodeStreamWriter generates duplicates when array elements
are not listed consecutively and interleaved with other sibling nodes.
Make sure to check if there is any previously processed sibling node
with the same node name instead of checking just the previous one.

Also, Add a couple of test cases to cover this issue.

JIRA: YANGTOOLS-1302
Change-Id: I4d64c8b8a45009e7667af621c96c34824fb7b48b
Signed-off-by: Manoj Chokka <cmanoj8@gmail.com>
Signed-off-by: Sangwook Ha <sangwook.ha@verizon.com>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java
codec/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/AnyXmlSupportTest.java
codec/yang-data-codec-gson/src/test/resources/complexjson/yang/yt1302.yang [new file with mode: 0644]
codec/yang-data-codec-gson/src/test/resources/yt1302/json/array-of-array.json [new file with mode: 0644]
codec/yang-data-codec-gson/src/test/resources/yt1302/json/flat-array.json [new file with mode: 0644]
codec/yang-data-codec-gson/src/test/resources/yt1302/xml/array-of-array.xml [new file with mode: 0644]
codec/yang-data-codec-gson/src/test/resources/yt1302/xml/flat-array.xml [new file with mode: 0644]

index 86ba2edebf4a4a06dfd9bdd139b3b5eb3d3f2e9a..811e5adfda15a9ddea01a6094932ed4adf0b2418 100644 (file)
@@ -14,6 +14,7 @@ import com.google.common.collect.ClassToInstanceMap;
 import com.google.common.collect.ImmutableClassToInstanceMap;
 import com.google.gson.stream.JsonWriter;
 import java.io.IOException;
+import java.util.HashSet;
 import java.util.NoSuchElementException;
 import java.util.regex.Pattern;
 import javax.xml.transform.dom.DOMSource;
@@ -552,12 +553,12 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
     }
 
     private void writeObject(Node node) throws IOException {
-        String previousNodeName = "";
+        final var previousNodeNames = new HashSet<String>();
         while (node != null) {
             if (Node.ELEMENT_NODE == node.getNodeType()) {
-                if (!node.getNodeName().equals(previousNodeName)) {
-                    previousNodeName = node.getNodeName();
-                    writer.name(node.getNodeName());
+                final var nodeName = node.getNodeName();
+                if (previousNodeNames.add(nodeName)) {
+                    writer.name(nodeName);
                     writeXmlNode(node);
                 }
             }
index 5f4656087711b95771eed0c205c8056685911050..bebb0dc619f58d27ed24bcad066ec94cc2c748b1 100644 (file)
@@ -131,7 +131,26 @@ public class AnyXmlSupportTest extends AbstractComplexJsonTest {
         executebug8927Test("/bug8927/xml/scalar_array.xml", "/bug8927/json/scalar_array.json");
     }
 
+    @Test
+    public void yt1302TestFlatArray() throws Exception {
+        executeYt1302Test("/yt1302/xml/flat-array.xml", "/yt1302/json/flat-array.json");
+    }
+
+    @Test
+    public void yt1302TestArrayOfArray() throws Exception {
+        executeYt1302Test("/yt1302/xml/array-of-array.xml", "/yt1302/json/array-of-array.json");
+    }
+
     private void executebug8927Test(final String inputXmlFile, final String expectedJsonFile) throws Exception {
+        verifyExpectedJson(inputXmlFile, expectedJsonFile, "bug8927.test", "2017-01-01", "foo");
+    }
+
+    private void executeYt1302Test(final String inputXmlFile, final String expectedJsonFile) throws Exception {
+        verifyExpectedJson(inputXmlFile, expectedJsonFile, "yt1302.test", "2022-10-11", "data");
+    }
+
+    private void verifyExpectedJson(final String inputXmlFile, final String expectedJsonFile,
+            final String namespace, final String revision, final String localName) throws Exception {
         final InputStream resourceAsStream = AnyXmlSupportTest.class.getResourceAsStream(inputXmlFile);
         final NormalizedNodeResult result = new NormalizedNodeResult();
         loadXmlToNormalizedNodes(resourceAsStream, result, schemaContext);
@@ -140,12 +159,12 @@ public class AnyXmlSupportTest extends AbstractComplexJsonTest {
         assertTrue(result.getResult() instanceof ContainerNode);
 
         final DataContainerChild data = ((ContainerNode) result.getResult())
-                .childByArg(new NodeIdentifier(QName.create("bug8927.test", "2017-01-01", "foo")));
+                .childByArg(new NodeIdentifier(QName.create(namespace, revision, localName)));
         assertNotNull(data);
         final String jsonOutput = normalizedNodesToJsonString(data, schemaContext);
         assertEquals(JsonParser.parseReader(new FileReader(
-            new File(getClass().getResource(expectedJsonFile).toURI()), StandardCharsets.UTF_8)),
-            JsonParser.parseString(jsonOutput));
+                        new File(getClass().getResource(expectedJsonFile).toURI()), StandardCharsets.UTF_8)),
+                JsonParser.parseString(jsonOutput));
     }
 
     private static DOMSource getParsedAnyXmlValue(final NormalizedNode transformedInput, final QName anyxmlName) {
diff --git a/codec/yang-data-codec-gson/src/test/resources/complexjson/yang/yt1302.yang b/codec/yang-data-codec-gson/src/test/resources/complexjson/yang/yt1302.yang
new file mode 100644 (file)
index 0000000..33ee970
--- /dev/null
@@ -0,0 +1,12 @@
+module yt1302 {
+    namespace "yt1302.test";
+    prefix yt1302;
+
+    revision 2022-10-11 {
+        description "Initial revision.";
+    }
+
+    container data {
+        anyxml anyxml-data;
+    }
+}
diff --git a/codec/yang-data-codec-gson/src/test/resources/yt1302/json/array-of-array.json b/codec/yang-data-codec-gson/src/test/resources/yt1302/json/array-of-array.json
new file mode 100644 (file)
index 0000000..25b82d2
--- /dev/null
@@ -0,0 +1,46 @@
+{
+    "yt1302:data": {
+        "anyxml-data": {
+            "list-a": [
+                {
+                    "list-a": [
+                        {
+                            "leaflist-a": [
+                                "alpha",
+                                "beta"
+                            ]
+                        },
+                        {
+                            "leaf-a": "epsilon"
+                        }
+                    ],
+                    "list-b": [
+                        {
+                            "leaflist-b": [
+                                "gamma",
+                                "delta"
+                            ]
+                        },
+                        {
+                            "leaf-b": "zeta"
+                        }
+                    ]
+                },
+                {
+                    "leaflist-a": [
+                        "theta",
+                        "iota"
+                    ]
+                }
+            ],
+            "list-b": [
+                {
+                    "leaf-b": "eta"
+                },
+                {
+                    "leaf-b": "kappa"
+                }
+            ]
+        }
+    }
+}
diff --git a/codec/yang-data-codec-gson/src/test/resources/yt1302/json/flat-array.json b/codec/yang-data-codec-gson/src/test/resources/yt1302/json/flat-array.json
new file mode 100644 (file)
index 0000000..0d4ab4d
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    "yt1302:data": {
+        "anyxml-data": {
+            "list-a": [
+                {
+                    "leaf-a": "alpha",
+                    "leaf-b": "beta"
+                },
+                {
+                    "leaf-a": "epsilon"
+                }
+            ],
+            "list-b": [
+                {
+                    "leaf-a": "gamma",
+                    "leaf-b": "delta"
+                },
+                {
+                    "leaf-a": "zeta"
+                }
+            ]
+        }
+    }
+}
diff --git a/codec/yang-data-codec-gson/src/test/resources/yt1302/xml/array-of-array.xml b/codec/yang-data-codec-gson/src/test/resources/yt1302/xml/array-of-array.xml
new file mode 100644 (file)
index 0000000..ebb22f0
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+<data xmlns="yt1302.test">
+    <anyxml-data>
+        <list-a>
+            <list-a>
+                <leaflist-a>alpha</leaflist-a>
+                <leaflist-a>beta</leaflist-a>
+            </list-a>
+            <list-b>
+                <leaflist-b>gamma</leaflist-b>
+                <leaflist-b>delta</leaflist-b>
+            </list-b>
+            <list-a>
+                <leaf-a>epsilon</leaf-a>
+            </list-a>
+            <list-b>
+                <leaf-b>zeta</leaf-b>
+            </list-b>
+        </list-a>
+        <list-b>
+            <leaf-b>eta</leaf-b>
+        </list-b>
+        <list-a>
+            <leaflist-a>theta</leaflist-a>
+            <leaflist-a>iota</leaflist-a>
+        </list-a>
+        <list-b>
+            <leaf-b>kappa</leaf-b>
+        </list-b>
+    </anyxml-data>
+</data>
+</root>
diff --git a/codec/yang-data-codec-gson/src/test/resources/yt1302/xml/flat-array.xml b/codec/yang-data-codec-gson/src/test/resources/yt1302/xml/flat-array.xml
new file mode 100644 (file)
index 0000000..4b74590
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+<data xmlns="yt1302.test">
+    <anyxml-data>
+        <list-a>
+            <leaf-a>alpha</leaf-a>
+            <leaf-b>beta</leaf-b>
+        </list-a>
+        <list-b>
+            <leaf-a>gamma</leaf-a>
+            <leaf-b>delta</leaf-b>
+        </list-b>
+        <list-a>
+            <leaf-a>epsilon</leaf-a>
+        </list-a>
+        <list-b>
+            <leaf-a>zeta</leaf-a>
+        </list-b>
+    </anyxml-data>
+</data>
+</root>