From 5babaa4fc00be0a587748c17b11f523ba8d61498 Mon Sep 17 00:00:00 2001 From: Igor Foltin Date: Tue, 25 Oct 2016 13:10:23 +0200 Subject: [PATCH] Bug 6814: Fix (de)serialization of anyxml in JSON JSON parser can now deserialize anyxml nodes. JSON serializer can now serialize anyxml nodes Change-Id: I815afb5aac82618f27cd26d747d6637eb4e962f0 Signed-off-by: Igor Foltin --- .../gson/JSONNormalizedNodeStreamWriter.java | 117 ++++++- .../data/codec/gson/JsonParserStream.java | 93 ++++-- .../data/codec/gson/AnyXmlSupportTest.java | 314 ++++++++++++++++++ .../gson/JsonStreamToNormalizedNodeTest.java | 21 -- .../gson/NormalizedNodeToJsonStreamTest.java | 21 -- ...ode-with-composite-value-in-container.json | 27 ++ ...l-node-with-simple-value-in-container.json | 7 + 7 files changed, 533 insertions(+), 67 deletions(-) create mode 100644 yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/AnyXmlSupportTest.java create mode 100644 yang/yang-data-codec-gson/src/test/resources/complexjson/anyxml-node-with-composite-value-in-container.json create mode 100644 yang/yang-data-codec-gson/src/test/resources/complexjson/anyxml-node-with-simple-value-in-container.json diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java index 27aedad9e8..2a1f8e1c99 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java @@ -7,10 +7,18 @@ */ 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; import java.net.URI; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.RegEx; +import javax.xml.transform.dom.DOMSource; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; @@ -22,6 +30,8 @@ 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.Node; +import org.w3c.dom.NodeList; /** * This implementation will create JSON output as output stream. @@ -36,6 +46,14 @@ public final class JSONNormalizedNodeStreamWriter implements NormalizedNodeStrea */ private static final boolean DEFAULT_EMIT_EMPTY_CONTAINERS = true; + @RegEx + private static final String NUMBER_STRING = "-?\\d+(\\.\\d+)?"; + private static final Pattern NUMBER_PATTERN = Pattern.compile(NUMBER_STRING); + + @RegEx + private static final String NOT_DECIMAL_NUMBER_STRING = "-?\\d+"; + private static final Pattern NOT_DECIMAL_NUMBER_PATTERN = Pattern.compile(NOT_DECIMAL_NUMBER_STRING); + private final SchemaTracker tracker; private final JSONCodecFactory codecs; private final JsonWriter writer; @@ -183,8 +201,8 @@ public final class JSONNormalizedNodeStreamWriter implements NormalizedNodeStrea context.emittingChild(codecs.getSchemaContext(), writer); context.writeChildJsonIdentifier(codecs.getSchemaContext(), writer, name.getNodeType()); - // FIXME this kind of serialization is incorrect since the value for AnyXml is now a DOMSource - writer.value(String.valueOf(value)); + + writeAnyXmlValue((DOMSource) value); } @Override @@ -208,6 +226,101 @@ public final class JSONNormalizedNodeStreamWriter implements NormalizedNodeStrea ((JSONCodec) codec).serializeToWriter(writer, value); } + 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())) { + writer.beginObject(); + traverseAnyXmlValue(documentNode); + 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()); + } + } + + // text value, i.e. a number, string, boolean or null + if (TEXT_NODE == childNode.getNodeType()) { + final String childNodeText = childNode.getNodeValue(); + final Matcher matcher = NUMBER_PATTERN.matcher(childNodeText); + if (matcher.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; + } + + traverseAnyXmlValue(childNode); + + if (inObject) { + writer.endObject(); + } + } + + if (inArray) { + writer.endArray(); + } + } + + // json numbers are 64 bit wide floating point numbers - in java terms it is either long or double + private static Number parseNumber(final String numberText) { + Matcher matcher = NOT_DECIMAL_NUMBER_PATTERN.matcher(numberText); + if (matcher.matches()) { + return Long.parseLong(numberText); + } else { + return Double.parseDouble(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(); diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java index 90ade685d9..c398384c26 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java @@ -24,6 +24,8 @@ import java.util.Collections; import java.util.Deque; import java.util.HashSet; import java.util.Set; +import javax.xml.transform.dom.DOMSource; +import org.opendaylight.yangtools.util.xml.UntrustedXML; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.util.AbstractNodeDataWithSchema; import org.opendaylight.yangtools.yang.data.util.AnyXmlNodeDataWithSchema; @@ -36,7 +38,6 @@ import org.opendaylight.yangtools.yang.data.util.ListNodeDataWithSchema; import org.opendaylight.yangtools.yang.data.util.ParserStreamUtils; import org.opendaylight.yangtools.yang.data.util.RpcAsContainer; import org.opendaylight.yangtools.yang.data.util.SimpleNodeDataWithSchema; -import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; @@ -46,6 +47,9 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Text; /** * This class parses JSON elements from a GSON JsonReader. It disallows multiple elements of the same name unlike the @@ -53,6 +57,8 @@ import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode; */ @Beta public final class JsonParserStream implements Closeable, Flushable { + static final String ANYXML_ARRAY_ELEMENT_ID = "array-element"; + private final Deque namespaces = new ArrayDeque<>(); private final NormalizedNodeStreamWriter writer; private final JSONCodecFactory codecs; @@ -111,15 +117,58 @@ public final class JsonParserStream implements Closeable, Flushable { } } - private void setValue(final AbstractNodeDataWithSchema parent, final String value) { - Preconditions.checkArgument(parent instanceof SimpleNodeDataWithSchema, "Node %s is not a simple type", - parent.getSchema().getQName()); - final SimpleNodeDataWithSchema parentSimpleNode = (SimpleNodeDataWithSchema) parent; - Preconditions.checkArgument(parentSimpleNode.getValue() == null, "Node '%s' has already set its value to '%s'", - parentSimpleNode.getSchema().getQName(), parentSimpleNode.getValue()); + private void traverseAnyXmlValue(final JsonReader in, final Document doc, final Element parentElement) + throws IOException { + switch (in.peek()) { + case STRING: + case NUMBER: + Text textNode = doc.createTextNode(in.nextString()); + parentElement.appendChild(textNode); + break; + case BOOLEAN: + textNode = doc.createTextNode(Boolean.toString(in.nextBoolean())); + parentElement.appendChild(textNode); + break; + case NULL: + in.nextNull(); + textNode = doc.createTextNode("null"); + parentElement.appendChild(textNode); + break; + case BEGIN_ARRAY: + in.beginArray(); + while (in.hasNext()) { + final Element childElement = doc.createElement(ANYXML_ARRAY_ELEMENT_ID); + parentElement.appendChild(childElement); + traverseAnyXmlValue(in, doc, childElement); + } + in.endArray(); + break; + case BEGIN_OBJECT: + in.beginObject(); + while (in.hasNext()) { + final Element childElement = doc.createElement(in.nextName()); + parentElement.appendChild(childElement); + traverseAnyXmlValue(in, doc, childElement); + } + in.endObject(); + case END_DOCUMENT: + case NAME: + case END_OBJECT: + case END_ARRAY: + break; + } + } - final Object translatedValue = translateValueByType(value, parentSimpleNode.getSchema()); - parentSimpleNode.setValue(translatedValue); + private void readAnyXmlValue(final JsonReader in, final AnyXmlNodeDataWithSchema parent, + final String anyXmlObjectName) throws IOException { + final String anyXmlObjectNS = getCurrentNamespace().toString(); + final Document doc = UntrustedXML.newDocumentBuilder().newDocument(); + final Element rootElement = doc.createElementNS(anyXmlObjectNS, anyXmlObjectName); + doc.appendChild(rootElement); + traverseAnyXmlValue(in, doc, rootElement); + + final DOMSource domSource = new DOMSource(doc.getDocumentElement()); + parent.setValue(domSource); } public void read(final JsonReader in, AbstractNodeDataWithSchema parent) throws IOException { @@ -182,13 +231,8 @@ public final class JsonParserStream implements Closeable, Flushable { } final AbstractNodeDataWithSchema newChild = ((CompositeNodeDataWithSchema) parent).addChild(childDataSchemaNodes); - /* - * FIXME:anyxml data shouldn't be skipped but should be loaded somehow. - * will be able to load anyxml which conforms to YANG data using these - * parser, for other anyxml will be harder. - */ if (newChild instanceof AnyXmlNodeDataWithSchema) { - in.skipValue(); + readAnyXmlValue(in, (AnyXmlNodeDataWithSchema) newChild, jsonElementName); } else { read(in, newChild); } @@ -221,15 +265,18 @@ public final class JsonParserStream implements Closeable, Flushable { return newChild; } + private void setValue(final AbstractNodeDataWithSchema parent, final String value) { + Preconditions.checkArgument(parent instanceof SimpleNodeDataWithSchema, "Node %s is not a simple type", + parent.getSchema().getQName()); + final SimpleNodeDataWithSchema parentSimpleNode = (SimpleNodeDataWithSchema) parent; + Preconditions.checkArgument(parentSimpleNode.getValue() == null, "Node '%s' has already set its value to '%s'", + parentSimpleNode.getSchema().getQName(), parentSimpleNode.getValue()); + + final Object translatedValue = translateValueByType(value, parentSimpleNode.getSchema()); + parentSimpleNode.setValue(translatedValue); + } + private Object translateValueByType(final String value, final DataSchemaNode node) { - if (node instanceof AnyXmlSchemaNode) { - /* - * FIXME: Figure out some YANG extension dispatch, which will - * reuse JSON parsing or XML parsing - anyxml is not well-defined in - * JSON. - */ - return value; - } return codecs.codecFor(node).deserialize(value); } diff --git a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/AnyXmlSupportTest.java b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/AnyXmlSupportTest.java new file mode 100644 index 0000000000..7fc8f04fb4 --- /dev/null +++ b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/AnyXmlSupportTest.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. 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.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadModules; +import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadTextFile; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URISyntaxException; +import javax.xml.transform.dom.DOMSource; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.yangtools.util.xml.UntrustedXML; +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; +import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode; +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; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Text; + +public class AnyXmlSupportTest { + + private static final QName CONT_1 = QName.create("ns:complex:json", "2014-08-11", "cont1"); + private static final QName LF12_ANY = QName.create(CONT_1, "lf12-any"); + private static final QName LF13_ANY = QName.create(CONT_1, "lf13-any"); + private static final QName LF14_ANY = QName.create(CONT_1, "lf14-any"); + + private static SchemaContext schemaContext; + + @BeforeClass + public static void setup() throws IOException, URISyntaxException, ReactorException { + schemaContext = loadModules("/complexjson/yang"); + } + + @Test + public void anyXmlNodeWithSimpleValueInContainer() throws IOException, URISyntaxException { + final String inputJson = loadTextFile("/complexjson/anyxml-node-with-simple-value-in-container.json"); + + // deserialization + final NormalizedNodeResult result = new NormalizedNodeResult(); + final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result); + final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext); + jsonParser.parse(new JsonReader(new StringReader(inputJson))); + final NormalizedNode transformedInput = result.getResult(); + assertNotNull(transformedInput); + + // lf12-any check + final DOMSource Lf12AnyActualValue = getParsedAnyXmlValue(transformedInput, LF12_ANY); + final DOMSource Lf12AnyExpectedValue = createAnyXmlSimpleValue("ns:complex:json", "lf12-any", "100.5"); + verifyTransformedAnyXmlNodeValue(Lf12AnyExpectedValue, Lf12AnyActualValue); + + // lf13-any check + final DOMSource Lf13AnyActualValue = getParsedAnyXmlValue(transformedInput, LF13_ANY); + final DOMSource Lf13AnyExpectedValue = createAnyXmlSimpleValue("ns:complex:json", "lf13-any", "true"); + verifyTransformedAnyXmlNodeValue(Lf13AnyExpectedValue, Lf13AnyActualValue); + + // lf14-any check + final DOMSource Lf14AnyActualValue = getParsedAnyXmlValue(transformedInput, LF14_ANY); + 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.create(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 JsonParser parser = new JsonParser(); + final JsonElement expected = parser.parse(inputJson); + final JsonElement actual = parser.parse(serializationResult); + assertTrue(expected.equals(actual)); + } + + @Test + public void anyXmlNodeWithCompositeValueInContainer() throws IOException, URISyntaxException { + final String inputJson = loadTextFile("/complexjson/anyxml-node-with-composite-value-in-container.json"); + + final NormalizedNodeResult result = new NormalizedNodeResult(); + final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result); + final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext); + jsonParser.parse(new JsonReader(new StringReader(inputJson))); + final NormalizedNode transformedInput = result.getResult(); + assertNotNull(transformedInput); + + // lf12-any check + final DOMSource Lf12AnyActualValue = getParsedAnyXmlValue(transformedInput, LF12_ANY); + final DOMSource Lf12AnyExpectedValue = createLf12AnyXmlCompositeValue("ns:complex:json", "lf12-any"); + verifyTransformedAnyXmlNodeValue(Lf12AnyExpectedValue, Lf12AnyActualValue); + + // lf13-any check + final DOMSource Lf13AnyActualValue = getParsedAnyXmlValue(transformedInput, LF13_ANY); + final DOMSource Lf13AnyExpectedValue = createLf13AnyXmlCompositeValue("ns:complex:json", "lf13-any"); + verifyTransformedAnyXmlNodeValue(Lf13AnyExpectedValue, Lf13AnyActualValue); + + // lf14-any check + final DOMSource Lf14AnyActualValue = getParsedAnyXmlValue(transformedInput, LF14_ANY); + final DOMSource Lf14AnyExpectedValue = createLf14AnyXmlCompositeValue("ns:complex:json", "lf14-any"); + verifyTransformedAnyXmlNodeValue(Lf14AnyExpectedValue, Lf14AnyActualValue); + + // serialization + final Writer writer = new StringWriter(); + final NormalizedNodeStreamWriter jsonStream = JSONNormalizedNodeStreamWriter. + createExclusiveWriter(JSONCodecFactory.create(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 JsonParser parser = new JsonParser(); + final JsonElement expected = parser.parse(inputJson); + final JsonElement actual = parser.parse(serializationResult); + assertTrue(expected.equals(actual)); + } + + private static DOMSource getParsedAnyXmlValue(final NormalizedNode transformedInput, final QName anyxmlName) { + assertTrue(transformedInput instanceof ContainerNode); + final ContainerNode cont1 = (ContainerNode) transformedInput; + final DataContainerChild child = cont1.getChild(new NodeIdentifier(anyxmlName)).get(); + assertNotNull(child); + assertTrue(child instanceof AnyXmlNode); + final AnyXmlNode anyXmlNode = (AnyXmlNode) child; + return anyXmlNode.getValue(); + } + + private static void verifyTransformedAnyXmlNodeValue(final DOMSource expectedValue, final DOMSource actualValue) { + assertTrue(expectedValue.getNode().isEqualNode(actualValue.getNode())); + } + + private static DOMSource createAnyXmlSimpleValue(final String ns, final String name, final String value) { + final Document doc = UntrustedXML.newDocumentBuilder().newDocument(); + final Element rootElement = doc.createElementNS(ns, name); + doc.appendChild(rootElement); + final Text textNode = doc.createTextNode(value); + rootElement.appendChild(textNode); + return new DOMSource(doc.getDocumentElement()); + } + + private static DOMSource createLf12AnyXmlCompositeValue(final String ns, final String name) { + final Document doc = UntrustedXML.newDocumentBuilder().newDocument(); + final Element rootElement = doc.createElementNS(ns, name); + + final Element arrayElement1 = doc.createElement("array-element"); + final Text arrayElement1Text = doc.createTextNode("true"); + arrayElement1.appendChild(arrayElement1Text); + + final Element arrayElement2 = doc.createElement("array-element"); + + final Element arrayElement2Baz = doc.createElement("baz"); + final Element bazArrayElement1 = doc.createElement("array-element"); + final Text bazArrayElement1Text = doc.createTextNode("120"); + bazArrayElement1.appendChild(bazArrayElement1Text); + final Element bazArrayElement2 = doc.createElement("array-element"); + final Text bazArrayElement2Text = doc.createTextNode("str-val"); + bazArrayElement2.appendChild(bazArrayElement2Text); + final Element bazArrayElement3 = doc.createElement("array-element"); + final Text bazArrayElement3Text = doc.createTextNode("false"); + bazArrayElement3.appendChild(bazArrayElement3Text); + + arrayElement2Baz.appendChild(bazArrayElement1); + arrayElement2Baz.appendChild(bazArrayElement2); + arrayElement2Baz.appendChild(bazArrayElement3); + + arrayElement2.appendChild(arrayElement2Baz); + + final Element arrayElement3 = doc.createElement("array-element"); + final Element arrayElement3Foo = doc.createElement("foo"); + final Text fooText = doc.createTextNode("null"); + arrayElement3Foo.appendChild(fooText); + arrayElement3.appendChild(arrayElement3Foo); + + rootElement.appendChild(arrayElement1); + rootElement.appendChild(arrayElement2); + rootElement.appendChild(arrayElement3); + + doc.appendChild(rootElement); + + return new DOMSource(doc.getDocumentElement()); + } + + private static DOMSource createLf13AnyXmlCompositeValue(final String ns, final String name) { + final Document doc = UntrustedXML.newDocumentBuilder().newDocument(); + final Element rootElement = doc.createElementNS(ns, name); + + final Element anyXmlArrayA = doc.createElement("anyxml-array-a"); + + final Element arrayAElement1 = doc.createElement("array-element"); + final Element arrayAElement1Foo = doc.createElement("foo"); + final Text fooText = doc.createTextNode("true"); + arrayAElement1Foo.appendChild(fooText); + arrayAElement1.appendChild(arrayAElement1Foo); + + final Element arrayAElement2 = doc.createElement("array-element"); + final Text arrayAElement2Text = doc.createTextNode("10"); + arrayAElement2.appendChild(arrayAElement2Text); + + final Element arrayAElement3 = doc.createElement("array-element"); + final Element arrayAElement3Bar = doc.createElement("bar"); + final Text barText = doc.createTextNode("false"); + arrayAElement3Bar.appendChild(barText); + arrayAElement3.appendChild(arrayAElement3Bar); + + anyXmlArrayA.appendChild(arrayAElement1); + anyXmlArrayA.appendChild(arrayAElement2); + anyXmlArrayA.appendChild(arrayAElement3); + + final Element anyXmlArrayB = doc.createElement("anyxml-array-b"); + + final Element arrayBElement1 = doc.createElement("array-element"); + final Text arrayBElement1Text = doc.createTextNode("1"); + arrayBElement1.appendChild(arrayBElement1Text); + + final Element arrayBElement2 = doc.createElement("array-element"); + final Text arrayBElement2Text = doc.createTextNode("2"); + arrayBElement2.appendChild(arrayBElement2Text); + + final Element arrayBElement3 = doc.createElement("array-element"); + + final Element arrayBElement3Element1 = doc.createElement("array-element"); + final Text arrayBElement3Element1Text = doc.createTextNode("4"); + arrayBElement3Element1.appendChild(arrayBElement3Element1Text); + final Element arrayBElement3Element2 = doc.createElement("array-element"); + final Text arrayBElement3Element2Text = doc.createTextNode("5"); + arrayBElement3Element2.appendChild(arrayBElement3Element2Text); + + arrayBElement3.appendChild(arrayBElement3Element1); + arrayBElement3.appendChild(arrayBElement3Element2); + + final Element arrayBElement4 = doc.createElement("array-element"); + final Text arrayBElement4Text = doc.createTextNode("7"); + arrayBElement4.appendChild(arrayBElement4Text); + + anyXmlArrayB.appendChild(arrayBElement1); + anyXmlArrayB.appendChild(arrayBElement2); + anyXmlArrayB.appendChild(arrayBElement3); + anyXmlArrayB.appendChild(arrayBElement4); + + rootElement.appendChild(anyXmlArrayA); + rootElement.appendChild(anyXmlArrayB); + + doc.appendChild(rootElement); + + return new DOMSource(doc.getDocumentElement()); + } + + private static DOMSource createLf14AnyXmlCompositeValue(final String ns, final String name) { + final Document doc = UntrustedXML.newDocumentBuilder().newDocument(); + final Element rootElement = doc.createElementNS(ns, name); + + final Element anyXmlObjectA = doc.createElement("anyxml-object-a"); + final Element dataA1 = doc.createElement("data-a1"); + final Text dataA1Text = doc.createTextNode("10"); + dataA1.appendChild(dataA1Text); + final Element dataA2 = doc.createElement("data-a2"); + final Text dataA2Text = doc.createTextNode("11"); + dataA2.appendChild(dataA2Text); + + anyXmlObjectA.appendChild(dataA1); + anyXmlObjectA.appendChild(dataA2); + + final Element anyXmlObjectB = doc.createElement("anyxml-object-b"); + + final Element childObjectB1 = doc.createElement("child-object-b1"); + final Element dataB1 = doc.createElement("data-b1"); + final Text dataB1Text = doc.createTextNode("5.5"); + dataB1.appendChild(dataB1Text); + childObjectB1.appendChild(dataB1); + + final Element childObjectB2 = doc.createElement("child-object-b2"); + final Element dataB2 = doc.createElement("data-b2"); + final Text dataB2Text = doc.createTextNode("b2-val"); + dataB2.appendChild(dataB2Text); + childObjectB2.appendChild(dataB2); + + anyXmlObjectB.appendChild(childObjectB1); + anyXmlObjectB.appendChild(childObjectB2); + + rootElement.appendChild(anyXmlObjectA); + rootElement.appendChild(anyXmlObjectB); + + doc.appendChild(rootElement); + + return new DOMSource(doc.getDocumentElement()); + } +} diff --git a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java index 25d8931540..96bb518cbd 100644 --- a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java +++ b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.io.StringReader; import java.net.URISyntaxException; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -52,26 +51,6 @@ public class JsonStreamToNormalizedNodeTest { schemaContext = loadModules("/complexjson/yang"); } - /** - * case when anyxml contains simple value will be implemented when anyxml normalized node reprezentation will be - * specified - */ - @Ignore - @Test - public void anyXmlNodeWithSimpleValueInContainer() throws IOException, URISyntaxException { - - } - - /** - * case when anyxml contains complex xml will be implemented when anyxml normalized node reprezentation will be - * specified - */ - @Ignore - @Test - public void anyXmlNodeWithCompositeValueInContainer() throws IOException, URISyntaxException { - - } - @Test public void leafNodeInContainer() throws IOException, URISyntaxException { final String inputJson = loadTextFile("/complexjson/leaf-node-in-container.json"); diff --git a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java index b78ff441cd..dd866c4b2f 100644 --- a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java +++ b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java @@ -28,7 +28,6 @@ import java.net.URISyntaxException; import java.util.HashSet; import java.util.Iterator; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -63,26 +62,6 @@ public class NormalizedNodeToJsonStreamTest { schemaContext = loadModules("/complexjson/yang"); } - /** - * case when anyxml contains simple value will be implemented when anyxml normalized node reprezentation will be - * specified - */ - @Ignore - @Test - public void anyXmlNodeWithSimpleValueInContainer() throws IOException, URISyntaxException { - - } - - /** - * case when anyxml contains complex xml will be implemented when anyxml normalized node reprezentation will be - * specified - */ - @Ignore - @Test - public void anyXmlNodeWithCompositeValueInContainer() throws IOException, URISyntaxException { - - } - @Test public void leafNodeInContainer() throws IOException, URISyntaxException { final Writer writer = new StringWriter(); diff --git a/yang/yang-data-codec-gson/src/test/resources/complexjson/anyxml-node-with-composite-value-in-container.json b/yang/yang-data-codec-gson/src/test/resources/complexjson/anyxml-node-with-composite-value-in-container.json new file mode 100644 index 0000000000..1bb60c4556 --- /dev/null +++ b/yang/yang-data-codec-gson/src/test/resources/complexjson/anyxml-node-with-composite-value-in-container.json @@ -0,0 +1,27 @@ +{ + "complexjson:cont1": { + "lf12-any": [true, {"baz": [120, "str-val", false]}, {"foo": null}], + + "lf13-any": { + "anyxml-array-a": [{"foo": true}, 10, {"bar": false}], + "anyxml-array-b": [1, 2, [4, 5], 7] + }, + + "lf14-any": { + "anyxml-object-a": { + "data-a1": 10, + "data-a2": 11 + }, + + "anyxml-object-b": { + "child-object-b1": { + "data-b1": 5.5 + }, + + "child-object-b2": { + "data-b2": "b2-val" + } + } + } + } +} \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/test/resources/complexjson/anyxml-node-with-simple-value-in-container.json b/yang/yang-data-codec-gson/src/test/resources/complexjson/anyxml-node-with-simple-value-in-container.json new file mode 100644 index 0000000000..930ba22c31 --- /dev/null +++ b/yang/yang-data-codec-gson/src/test/resources/complexjson/anyxml-node-with-simple-value-in-container.json @@ -0,0 +1,7 @@ +{ + "complexjson:cont1": { + "lf12-any": 100.5, + "lf13-any": true, + "lf14-any": null + } +} \ No newline at end of file -- 2.36.6