BUG 8927: Netconf response payload fails to render in JSON 94/65394/7
authorTomas Cere <tcere@cisco.com>
Tue, 3 Oct 2017 10:36:26 +0000 (12:36 +0200)
committerRobert Varga <nite@hq.sk>
Wed, 29 Nov 2017 09:53:42 +0000 (09:53 +0000)
JSONNormalizedNodeStreamWriter does not write a content of anyXml nodes
correctly mainly due to Text nodes containing whitespaces before, between
or after Element nodes. Therefore the first Text node only was serialized
to JSON and the rest of anyXML content was missing.
This patch provides fix of anyXml content serialization to JSON.

Added a fix for a null pointer for empty text node.

Change-Id: I74f34aecec1a85b2ede4be63e5b6dd74522981e4
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
Signed-off-by: Atul Gosain <agosain@luminanetworks.com>
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java
yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/AnyXmlSupportTest.java
yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/TestUtils.java
yang/yang-data-codec-gson/src/test/resources/bug8927/json/expected.json [new file with mode: 0644]
yang/yang-data-codec-gson/src/test/resources/bug8927/xml/input.xml [new file with mode: 0644]
yang/yang-data-codec-gson/src/test/resources/complexjson/yang/bug8927.yang [new file with mode: 0644]

index a3ba148e568d6e6a1a1796b9396a9662defc2767..cb1097b43ffe2da1afe3d6528ca6c9a32ce13ff4 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.data.codec.gson;
 
-import static org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream.ANYXML_ARRAY_ELEMENT_ID;
-import static org.w3c.dom.Node.ELEMENT_NODE;
-import static org.w3c.dom.Node.TEXT_NODE;
-
 import com.google.common.base.Preconditions;
 import com.google.gson.stream.JsonWriter;
 import java.io.IOException;
@@ -29,8 +25,14 @@ import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import static org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream.ANYXML_ARRAY_ELEMENT_ID;
+import static org.w3c.dom.Node.ELEMENT_NODE;
+import static org.w3c.dom.Node.TEXT_NODE;
 
 /**
  * This implementation will create JSON output as output stream.
@@ -233,77 +235,88 @@ public final class JSONNormalizedNodeStreamWriter implements NormalizedNodeStrea
     }
 
     private void writeAnyXmlValue(final DOMSource anyXmlValue) throws IOException {
-        final Node documentNode = anyXmlValue.getNode();
-        final Node firstChild = documentNode.getFirstChild();
-        if (ELEMENT_NODE == firstChild.getNodeType() && !ANYXML_ARRAY_ELEMENT_ID.equals(firstChild.getNodeName())) {
+        writeXmlNode(anyXmlValue.getNode());
+    }
+
+    private void writeXmlNode(final Node node) throws IOException {
+        final Element firstChildElement = getFirstChildElement(node);
+        if (firstChildElement == null) {
+            writeXmlValue(node);
+        } else if (ANYXML_ARRAY_ELEMENT_ID.equals(firstChildElement.getNodeName())) {
+            writer.beginArray();
+            writeArray(firstChildElement);
+            writer.endArray();
+        } else {
             writer.beginObject();
-            traverseAnyXmlValue(documentNode);
+            writeObject(firstChildElement);
             writer.endObject();
-        } else {
-            traverseAnyXmlValue(documentNode);
         }
     }
 
-    private void traverseAnyXmlValue(final Node node) throws IOException {
-        final NodeList children = node.getChildNodes();
-        boolean inArray = false;
-
-        for (int i = 0, length = children.getLength(); i < length; i++) {
-            final Node childNode = children.item(i);
-            boolean inObject = false;
-
-            if (ELEMENT_NODE == childNode.getNodeType()) {
-                final Node firstChild = childNode.getFirstChild();
-                // beginning of an array
-                if (ANYXML_ARRAY_ELEMENT_ID.equals(childNode.getNodeName()) && !inArray) {
-                    writer.beginArray();
-                    inArray = true;
-                    // object at the beginning of the array
-                    if (isJsonObjectInArray(childNode, firstChild)) {
-                        writer.beginObject();
-                        inObject = true;
-                    }
-                    // object in the array
-                } else if (isJsonObjectInArray(childNode, firstChild)) {
-                    writer.beginObject();
-                    inObject = true;
-                    // object
-                } else if (isJsonObject(firstChild)) {
-                    writer.name(childNode.getNodeName());
-                    writer.beginObject();
-                    inObject = true;
-                    // name
-                } else if (!inArray){
-                    writer.name(childNode.getNodeName());
-                }
+    private void writeArray(Node node) throws IOException {
+        while (node != null) {
+            if (ELEMENT_NODE == node.getNodeType()) {
+                writeXmlNode(node);
             }
+            node = node.getNextSibling();
+        }
+    }
 
-            // text value, i.e. a number, string, boolean or null
-            if (TEXT_NODE == childNode.getNodeType()) {
-                final String childNodeText = childNode.getNodeValue();
-                if (NUMBER_PATTERN.matcher(childNodeText).matches()) {
-                    writer.value(parseNumber(childNodeText));
-                } else if ("true".equals(childNodeText) || "false".equals(childNodeText)) {
-                    writer.value(Boolean.parseBoolean(childNodeText));
-                } else if ("null".equals(childNodeText)) {
-                    writer.nullValue();
-                } else {
-                    writer.value(childNodeText);
-                }
-
-                return;
+    private void writeObject(Node node) throws IOException {
+        while (node != null) {
+            if (ELEMENT_NODE == node.getNodeType()) {
+                writer.name(node.getNodeName());
+                writeXmlNode(node);
             }
+            node = node.getNextSibling();
+        }
+    }
+
+    private void writeXmlValue(final Node node) throws IOException {
+        Text firstChild = getFirstChildText(node);
 
-            traverseAnyXmlValue(childNode);
+        final String childNodeText = firstChild!=null
+                ? (firstChild.getWholeText()!=null ? firstChild.getWholeText().trim() : null)
+                : "null";
+        if (NUMBER_PATTERN.matcher(childNodeText).matches()) {
+            writer.value(parseNumber(childNodeText));
+            return;
+        }
+        switch (childNodeText) {
+            case "null":
+                writer.nullValue();
+                break;
+            case "false":
+                writer.value(false);
+                break;
+            case "true":
+                writer.value(true);
+                break;
+            default:
+                writer.value(childNodeText);
+        }
+    }
 
-            if (inObject) {
-                writer.endObject();
+    private static Element getFirstChildElement(final Node node) {
+        final NodeList children = node.getChildNodes();
+        for (int i = 0, length = children.getLength(); i < length; i++) {
+            final Node childNode = children.item(i);
+            if (ELEMENT_NODE == childNode.getNodeType()) {
+                return (Element) childNode;
             }
         }
+        return null;
+    }
 
-        if (inArray) {
-            writer.endArray();
+    private static Text getFirstChildText(final Node node) {
+        final NodeList children = node.getChildNodes();
+        for (int i = 0, length = children.getLength(); i < length; i++) {
+            final Node childNode = children.item(i);
+            if (TEXT_NODE == childNode.getNodeType()) {
+                return (Text) childNode;
+            }
         }
+        return null;
     }
 
     // json numbers are 64 bit wide floating point numbers - in java terms it is either long or double
@@ -315,16 +328,6 @@ public final class JSONNormalizedNodeStreamWriter implements NormalizedNodeStrea
         return Double.valueOf(numberText);
     }
 
-    private static boolean isJsonObject(final Node firstChild) {
-        return !ANYXML_ARRAY_ELEMENT_ID.equals(firstChild.getNodeName()) && TEXT_NODE != firstChild.getNodeType();
-    }
-
-    private static boolean isJsonObjectInArray(final Node node, final Node firstChild) {
-        return ANYXML_ARRAY_ELEMENT_ID.equals(node.getNodeName())
-                && !ANYXML_ARRAY_ELEMENT_ID.equals(firstChild.getNodeName())
-                && TEXT_NODE != firstChild.getNodeType();
-    }
-
     @Override
     public void flush() throws IOException {
         writer.flush();
index f64661b4121282b305a56ae02058245361834bf8..7c5af6c04be85491a0b136da90ddef9e7796cea2 100644 (file)
@@ -8,18 +8,23 @@
 
 package org.opendaylight.yangtools.yang.data.codec.gson;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadTextFile;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadXmlToNormalizedNodes;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.normalizedNodesToJsonString;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonParser;
 import com.google.gson.stream.JsonReader;
+import java.io.File;
+import java.io.FileReader;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
 import java.net.URISyntaxException;
+import com.google.common.base.Optional;
 import javax.xml.transform.dom.DOMSource;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -32,7 +37,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -84,15 +88,8 @@ public class AnyXmlSupportTest {
         final DOMSource Lf14AnyExpectedValue = createAnyXmlSimpleValue("ns:complex:json", "lf14-any", "null");
         verifyTransformedAnyXmlNodeValue(Lf14AnyExpectedValue, Lf14AnyActualValue);
 
-        // serialization
-        final Writer writer = new StringWriter();
-        final NormalizedNodeStreamWriter jsonStream = JSONNormalizedNodeStreamWriter.
-                createExclusiveWriter(JSONCodecFactory.getShared(schemaContext), SchemaPath.ROOT, null,
-                        JsonWriterFactory.createJsonWriter(writer, 2));
-        final NormalizedNodeWriter nodeWriter = NormalizedNodeWriter.forStreamWriter(jsonStream);
-        nodeWriter.write(transformedInput);
-        nodeWriter.close();
-        final String serializationResult = writer.toString();
+        final String serializationResult = normalizedNodesToJsonString(transformedInput, schemaContext,
+                SchemaPath.ROOT);
 
         final JsonParser parser = new JsonParser();
         final JsonElement expected = parser.parse(inputJson);
@@ -127,14 +124,8 @@ public class AnyXmlSupportTest {
         verifyTransformedAnyXmlNodeValue(Lf14AnyExpectedValue, Lf14AnyActualValue);
 
         // serialization
-        final Writer writer = new StringWriter();
-        final NormalizedNodeStreamWriter jsonStream = JSONNormalizedNodeStreamWriter.
-                createExclusiveWriter(JSONCodecFactory.getShared(schemaContext), SchemaPath.ROOT, null,
-                        JsonWriterFactory.createJsonWriter(writer, 2));
-        final NormalizedNodeWriter nodeWriter = NormalizedNodeWriter.forStreamWriter(jsonStream);
-        nodeWriter.write(transformedInput);
-        nodeWriter.close();
-        final String serializationResult = writer.toString();
+        final String serializationResult = normalizedNodesToJsonString(transformedInput, schemaContext,
+                SchemaPath.ROOT);
 
         final JsonParser parser = new JsonParser();
         final JsonElement expected = parser.parse(inputJson);
@@ -142,6 +133,29 @@ public class AnyXmlSupportTest {
         assertTrue(expected.equals(actual));
     }
 
+    @Test
+    public void bug8927Test() throws Exception {
+        final InputStream resourceAsStream = YangModeledAnyXmlSupportTest.class
+                .getResourceAsStream("/bug8927/xml/input.xml");
+        final NormalizedNodeResult result = new NormalizedNodeResult();
+        loadXmlToNormalizedNodes(resourceAsStream, result, schemaContext);
+
+        assertNotNull(result.getResult());
+        assertTrue(result.getResult() instanceof ContainerNode);
+
+        final Optional<DataContainerChild<? extends PathArgument, ?>> data = ((ContainerNode) result.getResult())
+                .getChild(new NodeIdentifier(QName.create("bug8927.test", "2017-01-01", "foo")));
+        assertTrue(data.isPresent());
+        final String jsonOutput = normalizedNodesToJsonString(data.get(), schemaContext, SchemaPath.ROOT);
+
+        final JsonParser parser = new JsonParser();
+        final JsonElement expextedJson = parser
+                .parse(new FileReader(new File(getClass().getResource("/bug8927/json/expected.json").toURI())));
+        final JsonElement serializedJson = parser.parse(jsonOutput);
+
+        assertEquals(expextedJson, serializedJson);
+    }
+
     private static DOMSource getParsedAnyXmlValue(final NormalizedNode<?, ?> transformedInput, final QName anyxmlName) {
         assertTrue(transformedInput instanceof ContainerNode);
         final ContainerNode cont1 = (ContainerNode) transformedInput;
index b98566e140562b5242734fe64691669286189a3c..c6b8bf693f98eeae104dc608ca06881b65074f34 100644 (file)
@@ -18,7 +18,20 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.net.URISyntaxException;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 
 public class TestUtils {
 
@@ -26,11 +39,11 @@ public class TestUtils {
     }
 
     static String loadTextFile(final File file) throws IOException {
-        FileReader fileReader = new FileReader(file);
-        BufferedReader bufReader = new BufferedReader(fileReader);
+        final FileReader fileReader = new FileReader(file);
+        final BufferedReader bufReader = new BufferedReader(fileReader);
 
         String line = null;
-        StringBuilder result = new StringBuilder();
+        final StringBuilder result = new StringBuilder();
         while ((line = bufReader.readLine()) != null) {
             result.append(line);
         }
@@ -42,9 +55,31 @@ public class TestUtils {
         return loadTextFile(new File(TestUtils.class.getResource(relativePath).toURI()));
     }
 
+    static void loadXmlToNormalizedNodes(final InputStream xmlInputStream, final NormalizedNodeResult result,
+            final SchemaContext schemaContext) throws Exception {
+        final XMLInputFactory factory = XMLInputFactory.newInstance();
+        final XMLStreamReader reader = factory.createXMLStreamReader(xmlInputStream);
+        final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+        final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
+        xmlParser.parse(reader);
+    }
+
+    static String normalizedNodesToJsonString(final NormalizedNode<?, ?> data, final SchemaContext schemaContext,
+            final SchemaPath rootPath) throws IOException {
+        final Writer writer = new StringWriter();
+        final NormalizedNodeStreamWriter jsonStream = JSONNormalizedNodeStreamWriter.createExclusiveWriter(
+                JSONCodecFactory.getShared(schemaContext), rootPath, null,
+                JsonWriterFactory.createJsonWriter(writer, 2));
+        final NormalizedNodeWriter nodeWriter = NormalizedNodeWriter.forStreamWriter(jsonStream);
+        nodeWriter.write(data);
+        nodeWriter.close();
+        final String serializationResult = writer.toString();
+        return serializationResult;
+    }
+
     static JsonObject childObject(final JsonObject jsonObject, final String... names) {
-        for (String name : names) {
-            JsonObject childJsonObject = jsonObject.getAsJsonObject(name);
+        for (final String name : names) {
+            final JsonObject childJsonObject = jsonObject.getAsJsonObject(name);
             if (childJsonObject != null) {
                 return childJsonObject;
             }
@@ -53,8 +88,8 @@ public class TestUtils {
     }
 
     static JsonPrimitive childPrimitive(final JsonObject jsonObject, final String... names) {
-        for (String name : names) {
-            JsonPrimitive childJsonPrimitive = jsonObject.getAsJsonPrimitive(name);
+        for (final String name : names) {
+            final JsonPrimitive childJsonPrimitive = jsonObject.getAsJsonPrimitive(name);
             if (childJsonPrimitive != null) {
                 return childJsonPrimitive;
             }
@@ -63,8 +98,8 @@ public class TestUtils {
     }
 
     static JsonArray childArray(final JsonObject jsonObject, final String... names) {
-        for (String name : names) {
-            JsonArray childJsonArray = jsonObject.getAsJsonArray(name);
+        for (final String name : names) {
+            final JsonArray childJsonArray = jsonObject.getAsJsonArray(name);
             if (childJsonArray != null) {
                 return childJsonArray;
             }
@@ -72,12 +107,12 @@ public class TestUtils {
         return null;
     }
 
-    static JsonObject resolveCont1(String jsonOutput) {
-        JsonParser parser = new JsonParser();
-        JsonElement rootElement = parser.parse(jsonOutput);
+    static JsonObject resolveCont1(final String jsonOutput) {
+        final JsonParser parser = new JsonParser();
+        final JsonElement rootElement = parser.parse(jsonOutput);
         assertTrue(rootElement.isJsonObject());
-        JsonObject rootObject = rootElement.getAsJsonObject();
-        JsonObject cont1 = childObject(rootObject, "complexjson:cont1", "cont1");
+        final JsonObject rootObject = rootElement.getAsJsonObject();
+        final JsonObject cont1 = childObject(rootObject, "complexjson:cont1", "cont1");
         return cont1;
     }
 
diff --git a/yang/yang-data-codec-gson/src/test/resources/bug8927/json/expected.json b/yang/yang-data-codec-gson/src/test/resources/bug8927/json/expected.json
new file mode 100644 (file)
index 0000000..b230c30
--- /dev/null
@@ -0,0 +1,121 @@
+{
+  "bug8927:foo": {
+    "alarm-information": {
+      "alarm-summary": {
+        "active-alarm-count": null
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-08-02 19:03:44 UTC",
+        "alarm-class": "Minor",
+        "alarm-description": "desc",
+        "alarm-short-description": "gnf-creation",
+        "alarm-type": "License"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Minor",
+        "alarm-description": "VMHost RE 0 host application failed",
+        "alarm-short-description": "VMHost RE 0 host ap",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "PDM 0 incompatible with chassis type",
+        "alarm-short-description": "PDM 0 incompatible",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "PDM 1 incompatible with chassis type",
+        "alarm-short-description": "PDM 1 incompatible",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "PDM 2 incompatible with chassis type",
+        "alarm-short-description": "PDM 2 incompatible",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "PDM 3 incompatible with chassis type",
+        "alarm-short-description": "PDM 3 incompatible",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "No Input Feed Selected for PSM 1",
+        "alarm-short-description": "No Input Feed Selec",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "No Input Feed Selected for PSM 2",
+        "alarm-short-description": "No Input Feed Selec",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "No Input Feed Selected for PSM 3",
+        "alarm-short-description": "No Input Feed Selec",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "No Input Feed Selected for PSM 4",
+        "alarm-short-description": "No Input Feed Selec",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "No Input Feed Selected for PSM 10",
+        "alarm-short-description": "No Input Feed Selec",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "No Input Feed Selected for PSM 11",
+        "alarm-short-description": "No Input Feed Selec",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "No Input Feed Selected for PSM 12",
+        "alarm-short-description": "No Input Feed Selec",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Major",
+        "alarm-description": "No Input Feed Selected for PSM 13",
+        "alarm-short-description": "No Input Feed Selec",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Minor",
+        "alarm-description": "VMHost RE 1 host application failed",
+        "alarm-short-description": "VMHost RE 1 host ap",
+        "alarm-type": "Chassis"
+      },
+      "alarm-detail": {
+        "alarm-time": "2017-07-25 16:04:31 UTC",
+        "alarm-class": "Minor",
+        "alarm-description": "Check plane 1 Fabric Chip",
+        "alarm-short-description": "Check plane 1 FCHIP",
+        "alarm-type": "Chassis"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yang/yang-data-codec-gson/src/test/resources/bug8927/xml/input.xml b/yang/yang-data-codec-gson/src/test/resources/bug8927/xml/input.xml
new file mode 100644 (file)
index 0000000..2d17641
--- /dev/null
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+<foo xmlns="bug8927.test">
+    <alarm-information xmlns="bug8927.test">
+        <alarm-summary>
+            <active-alarm-count/>
+        </alarm-summary>
+        <alarm-detail>
+            <alarm-time>
+                2017-08-02 19:03:44 UTC
+            </alarm-time>
+            <alarm-class>Minor</alarm-class>
+            <alarm-description>desc</alarm-description>
+            <alarm-short-description>gnf-creation</alarm-short-description>
+            <alarm-type>License</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Minor</alarm-class>
+            <alarm-description>VMHost RE 0 host application failed</alarm-description>
+            <alarm-short-description>VMHost RE 0 host ap</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>PDM 0 incompatible with chassis type</alarm-description>
+            <alarm-short-description>PDM 0 incompatible</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>PDM 1 incompatible with chassis type</alarm-description>
+            <alarm-short-description>PDM 1 incompatible</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>PDM 2 incompatible with chassis type</alarm-description>
+            <alarm-short-description>PDM 2 incompatible</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>PDM 3 incompatible with chassis type</alarm-description>
+            <alarm-short-description>PDM 3 incompatible</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>No Input Feed Selected for PSM 1</alarm-description>
+            <alarm-short-description>No Input Feed Selec</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>No Input Feed Selected for PSM 2</alarm-description>
+            <alarm-short-description>No Input Feed Selec</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>No Input Feed Selected for PSM 3</alarm-description>
+            <alarm-short-description>No Input Feed Selec</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>No Input Feed Selected for PSM 4</alarm-description>
+            <alarm-short-description>No Input Feed Selec</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>No Input Feed Selected for PSM 10</alarm-description>
+            <alarm-short-description>No Input Feed Selec</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>No Input Feed Selected for PSM 11</alarm-description>
+            <alarm-short-description>No Input Feed Selec</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>No Input Feed Selected for PSM 12</alarm-description>
+            <alarm-short-description>No Input Feed Selec</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Major</alarm-class>
+            <alarm-description>No Input Feed Selected for PSM 13</alarm-description>
+            <alarm-short-description>No Input Feed Selec</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Minor</alarm-class>
+            <alarm-description>VMHost RE 1 host application failed</alarm-description>
+            <alarm-short-description>VMHost RE 1 host ap</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+        <alarm-detail>
+            <alarm-time>
+                2017-07-25 16:04:31 UTC
+            </alarm-time>
+            <alarm-class>Minor</alarm-class>
+            <alarm-description>Check plane 1 Fabric Chip</alarm-description>
+            <alarm-short-description>Check plane 1 FCHIP</alarm-short-description>
+            <alarm-type>Chassis</alarm-type>
+        </alarm-detail>
+    </alarm-information>
+</foo>
+</root>
\ No newline at end of file
diff --git a/yang/yang-data-codec-gson/src/test/resources/complexjson/yang/bug8927.yang b/yang/yang-data-codec-gson/src/test/resources/complexjson/yang/bug8927.yang
new file mode 100644 (file)
index 0000000..05637fd
--- /dev/null
@@ -0,0 +1,12 @@
+module bug8927 {
+    namespace "bug8927.test";
+    prefix tst;
+
+    revision 2017-01-01 {
+    }
+
+    container foo {
+        anyxml alarm-information;
+    }
+}
+