import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.impl.codec.SchemaTracker;
+import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
if (parent == schema) {
endElement();
}
- } else if (schema instanceof ContainerSchemaNode || schema instanceof LeafSchemaNode) {
+ } else if (schema instanceof ContainerSchemaNode || schema instanceof LeafSchemaNode
+ || schema instanceof AnyDataSchemaNode) {
endElement();
}
}
checkState(current instanceof AnyXmlSchemaNode, "Unexpected scala value %s with %s", value, current);
anyxmlValue(value);
}
+
+ @Override
+ SchemaNode startAnydata(final NodeIdentifier name) {
+ return tracker.startAnydataNode(name);
+ }
}
break;
}
}
+
+ @Override
+ Object startAnydata(final NodeIdentifier name) {
+ nodeTypeStack.push(NodeType.ANY_XML);
+ return null;
+ }
}
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.dom.DOMSource;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.concepts.ObjectExtensions;
import org.opendaylight.yangtools.rfc7952.data.api.NormalizedMetadataStreamWriter;
+import org.opendaylight.yangtools.rfc7952.data.api.OpaqueAnydataStreamWriter;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriterExtension;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.OpaqueAnydataExtension;
import org.opendaylight.yangtools.yang.data.impl.codec.SchemaTracker;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
* removed in a future version.
*/
public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements NormalizedNodeStreamWriter,
- NormalizedMetadataStreamWriter {
+ NormalizedMetadataStreamWriter, OpaqueAnydataExtension {
private static final Logger LOG = LoggerFactory.getLogger(XMLStreamNormalizedNodeStreamWriter.class);
private static final Set<String> BROKEN_ATTRIBUTES = ConcurrentHashMap.newKeySet();
+ @SuppressWarnings("rawtypes")
+ static final ObjectExtensions.Factory<XMLStreamNormalizedNodeStreamWriter, NormalizedNodeStreamWriter,
+ NormalizedNodeStreamWriterExtension> EXTENSIONS_BUILDER = ObjectExtensions.factory(
+ XMLStreamNormalizedNodeStreamWriter.class, NormalizedMetadataStreamWriter.class,
+ OpaqueAnydataExtension.class);
+
private final @NonNull StreamWriterFacade facade;
XMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer) {
@Override
public final ClassToInstanceMap<NormalizedNodeStreamWriterExtension> getExtensions() {
- return ImmutableClassToInstanceMap.of(NormalizedMetadataStreamWriter.class, this);
+ return EXTENSIONS_BUILDER.newInstance(this);
}
+ abstract T startAnydata(NodeIdentifier name);
+
abstract void startList(NodeIdentifier name);
abstract void startListItem(PathArgument name) throws IOException;
}
}
}
+
+ @Override
+ public final OpaqueAnydataExtension.StreamWriter startOpaqueAnydataNode(final NodeIdentifier name,
+ final boolean accurateLists) throws IOException {
+ final T schema = startAnydata(name);
+ startElement(name.getNodeType());
+ return new XMLOpaqueStreamWriter(schema);
+ }
+
+ private final class XMLOpaqueStreamWriter implements OpaqueAnydataStreamWriter {
+ private final Deque<Boolean> stack = new ArrayDeque<>();
+ private final T valueContext;
+
+ XMLOpaqueStreamWriter(final T valueContext) {
+ this.valueContext = valueContext;
+ }
+
+ @Override
+ public void startOpaqueList(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ stack.push(Boolean.FALSE);
+ }
+
+ @Override
+ public void startOpaqueContainer(final NodeIdentifier name, final int childSizeHint) throws IOException {
+ stack.push(Boolean.TRUE);
+ startElement(name.getNodeType());
+ }
+
+ @Override
+ public void opaqueValue(final Object value) throws IOException {
+ writeValue(value, valueContext);
+ }
+
+ @Override
+ public void endOpaqueNode() throws IOException {
+ if (stack.pop()) {
+ endElement();
+ }
+ }
+
+ @Override
+ public boolean requireMetadataFirst() {
+ return true;
+ }
+
+ @Override
+ public void metadata(final ImmutableMap<QName, Object> metadata) throws IOException {
+ if (stack.peek()) {
+ XMLStreamNormalizedNodeStreamWriter.this.metadata(metadata);
+ } else {
+ LOG.debug("Ignoring metadata {}", metadata);
+ }
+ }
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.codec.xml;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public abstract class AbstractAnydataTest {
+ static final QName FOO_QNAME = QName.create("test-anydata", "foo");
+ static final QName BAR_QNAME = QName.create(FOO_QNAME, "bar");
+ static final NodeIdentifier FOO_NODEID = NodeIdentifier.create(FOO_QNAME);
+ static final NodeIdentifier BAR_NODEID = NodeIdentifier.create(BAR_QNAME);
+
+ static SchemaContext SCHEMA_CONTEXT;
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ SCHEMA_CONTEXT = YangParserTestUtils.parseYangResource("/test-anydata.yang");
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ SCHEMA_CONTEXT = null;
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.codec.xml;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Collection;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+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.Builders;
+import org.opendaylight.yangtools.yang.data.util.schema.opaque.OpaqueDataBuilder;
+import org.opendaylight.yangtools.yang.data.util.schema.opaque.OpaqueDataContainerBuilder;
+import org.opendaylight.yangtools.yang.data.util.schema.opaque.OpaqueDataListBuilder;
+
+@RunWith(Parameterized.class)
+public class AnydataSerializeTest extends AbstractAnydataTest {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> data() {
+ return TestFactories.junitParameters();
+ }
+
+ private final XMLOutputFactory factory;
+
+ public AnydataSerializeTest(final String factoryMode, final XMLOutputFactory factory) {
+ this.factory = factory;
+ }
+
+ @Test
+ public void testOpaqueAnydata() throws XMLStreamException, IOException {
+ final StringWriter writer = new StringWriter();
+ final XMLStreamWriter xmlStreamWriter = factory.createXMLStreamWriter(writer);
+
+ final NormalizedNodeStreamWriter xmlNormalizedNodeStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(
+ xmlStreamWriter, SCHEMA_CONTEXT);
+ final NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(
+ xmlNormalizedNodeStreamWriter);
+ normalizedNodeWriter.write(Builders.opaqueAnydataBuilder().withNodeIdentifier(FOO_NODEID)
+ .withValue(new OpaqueDataBuilder().withAccurateLists(false)
+ .withRoot(
+ new OpaqueDataListBuilder().withIdentifier(BAR_NODEID)
+ .withChild(new OpaqueDataContainerBuilder().withIdentifier(BAR_NODEID).build())
+ .build())
+ .build())
+ .build());
+ normalizedNodeWriter.flush();
+
+ final String serializedXml = writer.toString();
+ assertEquals("<foo xmlns=\"test-anydata\"><bar/></foo>", serializedXml);
+ }
+}
--- /dev/null
+module test-anydata {
+ yang-version 1.1;
+ namespace test-anydata;
+ prefix ta;
+
+ anydata foo;
+}
+
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
schemaStack.push(anyxmlNode(name));
}
+ public AnyDataSchemaNode anydataNode(final NodeIdentifier name) {
+ final SchemaNode schema = getSchema(name);
+ checkArgument(schema instanceof AnyDataSchemaNode, "Node %s is not anydata", schema.getPath());
+ return (AnyDataSchemaNode)schema;
+ }
+
+ public AnyDataSchemaNode startAnydataNode(final NodeIdentifier name) {
+ final AnyDataSchemaNode ret = anydataNode(name);
+ schemaStack.push(ret);
+ return ret;
+ }
+
public Object endNode() {
return schemaStack.pop();
}