Add support for attributes int NN stream writer 50/16250/2
authorMaros Marsalek <mmarsale@cisco.com>
Tue, 10 Mar 2015 10:50:10 +0000 (11:50 +0100)
committerMaros Marsalek <mmarsale@cisco.com>
Tue, 10 Mar 2015 11:08:04 +0000 (12:08 +0100)
Change-Id: I51dc747763a65dee5145a33657eaf7223945d096
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/NormalizedNodeStreamAttributeWriter.java [new file with mode: 0644]
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/NormalizedNodeWriter.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XMLStreamNormalizedNodeStreamWriter.java

diff --git a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/NormalizedNodeStreamAttributeWriter.java b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/NormalizedNodeStreamAttributeWriter.java
new file mode 100644 (file)
index 0000000..ca0e342
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014 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.api.schema.stream;
+
+import java.io.IOException;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * Extension to the NormalizedNodeStreamWriter with attribute support
+ */
+public interface NormalizedNodeStreamAttributeWriter extends NormalizedNodeStreamWriter {
+
+    void leafNode(YangInstanceIdentifier.NodeIdentifier name, Object value, Map<QName, String> attributes) throws IOException, IllegalArgumentException;
+
+    void leafSetEntryNode(Object value, Map<QName, String> attributes) throws IOException, IllegalArgumentException;
+
+    void startContainerNode(YangInstanceIdentifier.NodeIdentifier name, int childSizeHint, Map<QName, String> attributes) throws IOException, IllegalArgumentException;
+
+    void startUnkeyedListItem(YangInstanceIdentifier.NodeIdentifier name, int childSizeHint, Map<QName, String> attributes) throws IOException, IllegalStateException;
+
+    void startMapEntryNode(YangInstanceIdentifier.NodeIdentifierWithPredicates identifier, int childSizeHint, Map<QName, String> attributes) throws IOException, IllegalArgumentException;
+}
index 6a19b45f376a02b5d0346f3a28a7b704f0c6e098..7b567f6423bbbcf79d326ceee66f54c25b1187d6 100644 (file)
@@ -14,15 +14,12 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
-
 import java.io.Closeable;
 import java.io.Flushable;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Set;
-
 import javax.xml.stream.XMLStreamReader;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
@@ -137,11 +134,19 @@ public class NormalizedNodeWriter implements Closeable, Flushable {
     private boolean wasProcessAsSimpleNode(final NormalizedNode<?, ?> node) throws IOException {
         if (node instanceof LeafSetEntryNode) {
             final LeafSetEntryNode<?> nodeAsLeafList = (LeafSetEntryNode<?>)node;
-            writer.leafSetEntryNode(nodeAsLeafList.getValue());
+            if(writer instanceof NormalizedNodeStreamAttributeWriter) {
+                ((NormalizedNodeStreamAttributeWriter) writer).leafSetEntryNode(nodeAsLeafList.getValue(), nodeAsLeafList.getAttributes());
+            } else {
+                writer.leafSetEntryNode(nodeAsLeafList.getValue());
+            }
             return true;
         } else if (node instanceof LeafNode) {
             final LeafNode<?> nodeAsLeaf = (LeafNode<?>)node;
-            writer.leafNode(nodeAsLeaf.getIdentifier(), nodeAsLeaf.getValue());
+            if(writer instanceof NormalizedNodeStreamAttributeWriter) {
+                ((NormalizedNodeStreamAttributeWriter) writer).leafNode(nodeAsLeaf.getIdentifier(), nodeAsLeaf.getValue(), nodeAsLeaf.getAttributes());
+            } else {
+                writer.leafNode(nodeAsLeaf.getIdentifier(), nodeAsLeaf.getValue());
+            }
             return true;
         } else if (node instanceof AnyXmlNode) {
             final AnyXmlNode anyXmlNode = (AnyXmlNode)node;
@@ -169,14 +174,23 @@ public class NormalizedNodeWriter implements Closeable, Flushable {
     }
 
     protected boolean writeMapEntryNode(final MapEntryNode node) throws IOException {
-        writer.startMapEntryNode(node.getIdentifier(), childSizeHint(node.getValue()));
+        if(writer instanceof NormalizedNodeStreamAttributeWriter) {
+            ((NormalizedNodeStreamAttributeWriter) writer)
+                    .startMapEntryNode(node.getIdentifier(), childSizeHint(node.getValue()), node.getAttributes());
+        } else {
+            writer.startMapEntryNode(node.getIdentifier(), childSizeHint(node.getValue()));
+        }
         return writeChildren(node.getValue());
     }
 
     private boolean wasProcessedAsCompositeNode(final NormalizedNode<?, ?> node) throws IOException {
         if (node instanceof ContainerNode) {
             final ContainerNode n = (ContainerNode) node;
-            writer.startContainerNode(n.getIdentifier(), childSizeHint(n.getValue()));
+            if(writer instanceof NormalizedNodeStreamAttributeWriter) {
+                ((NormalizedNodeStreamAttributeWriter) writer).startContainerNode(n.getIdentifier(), childSizeHint(n.getValue()), n.getAttributes());
+            } else {
+                writer.startContainerNode(n.getIdentifier(), childSizeHint(n.getValue()));
+            }
             return writeChildren(n.getValue());
         }
         if (node instanceof MapEntryNode) {
index ddc8076d612cd2b4af752920655b9fed58729a4c..e8e2f927229e39d2e894e41da013c482219ba908 100644 (file)
@@ -7,10 +7,12 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.codec.xml;
 
-import static javax.xml.XMLConstants.DEFAULT_NS_PREFIX;
-
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Map;
+import javax.xml.XMLConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -19,6 +21,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.Augmentat
 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.NormalizedNodeStreamAttributeWriter;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.codec.SchemaTracker;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
@@ -35,16 +38,18 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
  * A {@link NormalizedNodeStreamWriter} which translates the events into an
  * {@link XMLStreamWriter}, resulting in a RFC 6020 XML encoding.
  */
-public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter {
+public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNodeStreamAttributeWriter {
 
     private final XMLStreamWriter writer;
     private final SchemaTracker tracker;
     private final XmlStreamUtils streamUtils;
+    private RandomPrefix randomPrefix;
 
     private XMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer, final SchemaContext context, final SchemaPath path) {
         this.writer = Preconditions.checkNotNull(writer);
         this.tracker = SchemaTracker.create(context, path);
         this.streamUtils = XmlStreamUtils.create(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, context);
+        randomPrefix = new RandomPrefix();
     }
 
     /**
@@ -72,9 +77,9 @@ public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNode
 
     private void writeStartElement( QName qname) throws XMLStreamException {
         String ns = qname.getNamespace().toString();
-        writer.writeStartElement(DEFAULT_NS_PREFIX, qname.getLocalName(), ns);
+        writer.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, qname.getLocalName(), ns);
         if(writer.getNamespaceContext() != null) {
-            String parentNs = writer.getNamespaceContext().getNamespaceURI(DEFAULT_NS_PREFIX);
+            String parentNs = writer.getNamespaceContext().getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX);
             if (!ns.equals(parentNs)) {
                 writer.writeDefaultNamespace(ns);
             }
@@ -105,6 +110,19 @@ public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNode
         }
     }
 
+    private void writeElement(final QName qname, final SchemaNode schemaNode, final Object value, final Map<QName, String> attributes) throws IOException {
+        try {
+            writeStartElement(qname);
+            writeAttributes(attributes);
+            if (value != null) {
+                streamUtils.writeValue(writer, schemaNode, value);
+            }
+            writer.writeEndElement();
+        } catch (XMLStreamException e) {
+            throw new IOException("Failed to emit element", e);
+        }
+    }
+
     private void startElement(final QName qname) throws IOException {
         try {
             writeStartElement(qname);
@@ -128,6 +146,52 @@ public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNode
         writeElement(schema.getQName(), schema, value);
     }
 
+    @Override
+    public void leafNode(final NodeIdentifier name, final Object value, final Map<QName, String> attributes) throws IOException {
+        final LeafSchemaNode schema = tracker.leafNode(name);
+        writeElement(schema.getQName(), schema, value, attributes);
+    }
+
+    @Override
+    public void leafSetEntryNode(final Object value, final Map<QName, String> attributes) throws IOException, IllegalArgumentException {
+        final LeafListSchemaNode schema = tracker.leafSetEntryNode();
+        writeElement(schema.getQName(), schema, value, attributes);
+    }
+
+    @Override
+    public void startContainerNode(final NodeIdentifier name, final int childSizeHint, final Map<QName, String> attributes) throws IOException, IllegalArgumentException {
+        startContainerNode(name, childSizeHint);
+        writeAttributes(attributes);
+    }
+
+    @Override
+    public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint, final Map<QName, String> attributes) throws IOException, IllegalStateException {
+        startUnkeyedListItem(name, childSizeHint);
+        writeAttributes(attributes);
+    }
+
+    @Override
+    public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint, final Map<QName, String> attributes) throws IOException, IllegalArgumentException {
+        startMapEntryNode(identifier, childSizeHint);
+        writeAttributes(attributes);
+    }
+
+    private void writeAttributes(final Map<QName, String> attributes) throws IOException {
+        for (final Map.Entry<QName, String> qNameStringEntry : attributes.entrySet()) {
+            try {
+                final String namespace = qNameStringEntry.getKey().getNamespace().toString();
+                if(Strings.isNullOrEmpty(namespace)) {
+                    writer.writeAttribute(qNameStringEntry.getKey().getLocalName(), qNameStringEntry.getValue());
+                } else {
+                    final String prefix = randomPrefix.encodePrefix(qNameStringEntry.getKey().getNamespace());
+                    writer.writeAttribute(prefix, namespace, qNameStringEntry.getKey().getLocalName(), qNameStringEntry.getValue());
+                }
+            } catch (final XMLStreamException e) {
+                throw new IOException("Unable to emit attribute " + qNameStringEntry, e);
+            }
+        }
+    }
+
     @Override
     public void startLeafSet(final NodeIdentifier name, final int childSizeHint) {
         tracker.startLeafSet(name);