Merge "BUG-1281: switch serialization to use StAX APIs"
authorTony Tkacik <ttkacik@cisco.com>
Mon, 21 Jul 2014 09:07:11 +0000 (09:07 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 21 Jul 2014 09:07:11 +0000 (09:07 +0000)
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java

index 53f768c072e9bb1dcae93077c08b62bd2d117f77..ce2f036f16153e3e5383e32467304a00c5555fe6 100644 (file)
@@ -27,6 +27,10 @@ import javax.activation.UnsupportedDataTypeException;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.dom.DOMResult;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
@@ -62,7 +66,6 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
 public class XmlDocumentUtils {
-
     private static class ElementWithSchemaContext {
         Element element;
         SchemaContext schemaContext;
@@ -81,16 +84,16 @@ public class XmlDocumentUtils {
         }
     }
 
+    public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation");
+    private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class);
+    private static final XMLOutputFactory FACTORY = XMLOutputFactory.newFactory();
     private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() {
-
         @Override
         public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(final TypeDefinition<?> baseType) {
             return TypeDefinitionAwareCodec.from(baseType);
         }
     };
 
-    private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class);
-
     /**
      * Converts Data DOM structure to XML Document for specified XML Codec Provider and corresponding
      * Data Node Container schema. The CompositeNode data parameter enters as root of Data DOM tree and will
@@ -108,14 +111,19 @@ public class XmlDocumentUtils {
         Preconditions.checkNotNull(data);
         Preconditions.checkNotNull(schema);
 
-        Document doc = getDocument();
+        if (!(schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode)) {
+            throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+        }
 
-        if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
-            doc.appendChild(createXmlRootElement(doc, data, (SchemaNode) schema, codecProvider));
-            return doc;
-        } else {
-            throw new UnsupportedDataTypeException(
-                    "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+        final DOMResult result = new DOMResult();
+        try {
+            final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result);
+            XmlStreamUtils.create(codecProvider).writeDocument(writer, data, (SchemaNode)schema);
+            writer.close();
+            return (Document)result.getNode();
+        } catch (XMLStreamException e) {
+            logger.error("Failed to serialize data {}", data, e);
+            return null;
         }
     }
 
@@ -141,57 +149,17 @@ public class XmlDocumentUtils {
      * @return new instance of XML Document
      * @throws UnsupportedDataTypeException
      */
-    public static Document toDocument(final CompositeNode data, final XmlCodecProvider codecProvider)
-            throws UnsupportedDataTypeException {
-        Preconditions.checkNotNull(data);
-
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        dbf.setNamespaceAware(true);
-        Document doc = null;
+    public static Document toDocument(final CompositeNode data, final XmlCodecProvider codecProvider) {
+        final DOMResult result = new DOMResult();
         try {
-            DocumentBuilder bob = dbf.newDocumentBuilder();
-            doc = bob.newDocument();
-        } catch (ParserConfigurationException e) {
+            final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result);
+            XmlStreamUtils.create(codecProvider).writeDocument(writer, data);
+            writer.close();
+            return (Document)result.getNode();
+        } catch (XMLStreamException e) {
+            logger.error("Failed to serialize data {}", data, e);
             return null;
         }
-
-        doc.appendChild(createXmlRootElement(doc, data, null, codecProvider));
-        return doc;
-    }
-
-    private static Element createXmlRootElement(final Document doc, final Node<?> data, final SchemaNode schema,
-            final XmlCodecProvider codecProvider) throws UnsupportedDataTypeException {
-        Element itemEl = createElementFor(doc, data);
-        if (data instanceof SimpleNode<?>) {
-            if (schema instanceof LeafListSchemaNode) {
-                writeValueByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType(),
-                        (DataSchemaNode) schema, codecProvider);
-            } else if (schema instanceof LeafSchemaNode) {
-                writeValueByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType(),
-                        (DataSchemaNode) schema, codecProvider);
-            } else {
-                Object value = data.getValue();
-                if (value != null) {
-                    itemEl.setTextContent(String.valueOf(value));
-                }
-            }
-        } else { // CompositeNode
-            for (Node<?> child : ((CompositeNode) data).getValue()) {
-                DataSchemaNode childSchema = null;
-                if (schema instanceof DataNodeContainer) {
-                    childSchema = findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
-                    if (logger.isDebugEnabled()) {
-                        if (childSchema == null) {
-                            logger.debug("Probably the data node \""
-                                    + ((child == null) ? "" : child.getNodeType().getLocalName())
-                                    + "\" is not conform to schema");
-                        }
-                    }
-                }
-                itemEl.appendChild(createXmlRootElement(doc, child, childSchema, codecProvider));
-            }
-        }
-        return itemEl;
     }
 
     private static final Element createElementFor(final Document doc, final QName qname, final Object obj) {
@@ -376,8 +344,6 @@ public class XmlDocumentUtils {
         return ImmutableCompositeNode.create(qName, values, modifyAction.orNull());
     }
 
-    public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation");
-
     public static Optional<ModifyAction> getModifyOperationFromAttributes(final Element xmlElement) {
         Attr attributeNodeNS = xmlElement.getAttributeNodeNS(OPERATION_ATTRIBUTE_QNAME.getNamespace().toString(), OPERATION_ATTRIBUTE_QNAME.getLocalName());
         if(attributeNodeNS == null) {