*/
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;
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.
*/
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;
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
((JSONCodec<Object>) 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();
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;
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;
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
*/
@Beta
public final class JsonParserStream implements Closeable, Flushable {
+ static final String ANYXML_ARRAY_ELEMENT_ID = "array-element";
+
private final Deque<URI> namespaces = new ArrayDeque<>();
private final NormalizedNodeStreamWriter writer;
private final JSONCodecFactory codecs;
}
}
- 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 {
}
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);
}
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);
}
--- /dev/null
+/*
+ * 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<? extends PathArgument, ?> 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());
+ }
+}