Refactor implementations to hide XMLStreamWriter
[yangtools.git] / yang / yang-data-codec-xml / src / main / java / org / opendaylight / yangtools / yang / data / codec / xml / XMLStreamNormalizedNodeStreamWriter.java
index 0a287f5b59617e9bd5594a2268aee10b35f6ed95..55e4e93b243bd439326b77b7bd459e2e308aa9b3 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.yangtools.yang.data.codec.xml;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.base.Strings;
 import java.io.IOException;
 import java.io.StringWriter;
@@ -16,8 +18,6 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import javax.xml.XMLConstants;
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.stream.XMLStreamException;
@@ -30,6 +30,8 @@ import javax.xml.transform.TransformerFactoryConfigurationError;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stax.StAXResult;
 import javax.xml.transform.stream.StreamResult;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 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;
@@ -54,7 +56,7 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
     private static final String COM_SUN_TRANSFORMER =
         "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
 
-    private static final TransformerFactory TRANSFORMER_FACTORY;
+    static final TransformerFactory TRANSFORMER_FACTORY;
 
     static {
         TransformerFactory fa = TransformerFactory.newInstance();
@@ -72,11 +74,11 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
 
     private static final Set<String> BROKEN_NAMESPACES = ConcurrentHashMap.newKeySet();
 
+    private final @NonNull XMLStreamWriter writer;
     private final RandomPrefix prefixes;
-    final XMLStreamWriter writer;
 
     XMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer) {
-        this.writer = Preconditions.checkNotNull(writer);
+        this.writer = requireNonNull(writer);
         this.prefixes = new RandomPrefix(writer.getNamespaceContext());
     }
 
@@ -100,9 +102,9 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
      *
      * @return A new {@link NormalizedNodeStreamWriter}
      */
-    public static NormalizedNodeStreamWriter create(final XMLStreamWriter writer, final SchemaContext context,
+    public static @NonNull NormalizedNodeStreamWriter create(final XMLStreamWriter writer, final SchemaContext context,
             final SchemaPath path) {
-        return SchemaAwareXMLStreamNormalizedNodeStreamWriter.newInstance(writer, context, path);
+        return new SchemaAwareXMLStreamNormalizedNodeStreamWriter(writer, context, path);
     }
 
     /**
@@ -113,18 +115,18 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
      *
      * @return A new {@link NormalizedNodeStreamWriter}
      */
-    public static NormalizedNodeStreamWriter createSchemaless(final XMLStreamWriter writer) {
-        return SchemalessXMLStreamNormalizedNodeStreamWriter.newInstance(writer);
+    public static @NonNull NormalizedNodeStreamWriter createSchemaless(final XMLStreamWriter writer) {
+        return new SchemalessXMLStreamNormalizedNodeStreamWriter(writer);
     }
 
-    abstract void writeValue(final XMLStreamWriter xmlWriter, final QName qname,
-            @Nonnull final Object value, T context) throws IOException, XMLStreamException;
+    abstract void writeValue(@NonNull XMLStreamWriter xmlWriter, QName qname, @NonNull Object value, T context)
+            throws IOException, XMLStreamException;
 
-    abstract void startList(final NodeIdentifier name);
+    abstract void startList(NodeIdentifier name);
 
-    abstract void startListItem(final PathArgument name) throws IOException;
+    abstract void startListItem(PathArgument name) throws IOException;
 
-    private void writeAttributes(@Nonnull final Map<QName, String> attributes) throws IOException {
+    private void writeAttributes(final @NonNull Map<QName, String> attributes) throws IOException {
         for (final Entry<QName, String> entry : attributes.entrySet()) {
             try {
                 final QName qname = entry.getKey();
@@ -159,22 +161,30 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
     }
 
     private void writeStartElement(final QName qname) throws XMLStreamException {
-        String ns = qname.getNamespace().toString();
+        final String ns = qname.getNamespace().toString();
+        final NamespaceContext context = writer.getNamespaceContext();
+        final boolean needDefaultNs;
+        if (context != null) {
+            final String parentNs = context.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX);
+            needDefaultNs = !ns.equals(parentNs);
+        } else {
+            needDefaultNs = false;
+        }
+
         writer.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, qname.getLocalName(), ns);
-        if (writer.getNamespaceContext() != null) {
-            String parentNs = writer.getNamespaceContext().getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX);
-            if (!ns.equals(parentNs)) {
-                writer.writeDefaultNamespace(ns);
-            }
+        if (needDefaultNs) {
+            writer.writeDefaultNamespace(ns);
         }
     }
 
-    void writeElement(final QName qname, final Object value, @Nullable final Map<QName, String> attributes,
+    final void writeElement(final QName qname, final Object value, final @Nullable Map<QName, String> attributes,
             final T context) throws IOException {
         try {
             writeStartElement(qname);
 
-            writeAttributes(attributes);
+            if (attributes != null) {
+                writeAttributes(attributes);
+            }
             if (value != null) {
                 writeValue(writer, qname, value, context);
             }
@@ -184,7 +194,7 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
         }
     }
 
-    void startElement(final QName qname) throws IOException {
+    final void startElement(final QName qname) throws IOException {
         try {
             writeStartElement(qname);
         } catch (XMLStreamException e) {
@@ -192,13 +202,21 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
         }
     }
 
-    void anyxmlNode(final QName qname, final Object value) throws IOException {
+    final void endElement() throws IOException {
+        try {
+            writer.writeEndElement();
+        } catch (XMLStreamException e) {
+            throw new IOException("Failed to end element", e);
+        }
+    }
+
+    final void anyxmlNode(final QName qname, final Object value) throws IOException {
         if (value != null) {
-            Preconditions.checkArgument(value instanceof DOMSource, "AnyXML value must be DOMSource, not %s", value);
+            checkArgument(value instanceof DOMSource, "AnyXML value must be DOMSource, not %s", value);
             final DOMSource domSource = (DOMSource) value;
-            Preconditions.checkNotNull(domSource.getNode());
-            Preconditions.checkArgument(domSource.getNode().getNodeName().equals(qname.getLocalName()));
-            Preconditions.checkArgument(domSource.getNode().getNamespaceURI().equals(qname.getNamespace().toString()));
+            requireNonNull(domSource.getNode());
+            checkArgument(domSource.getNode().getNodeName().equals(qname.getLocalName()));
+            checkArgument(domSource.getNode().getNamespaceURI().equals(qname.getNamespace().toString()));
             try {
                 // TODO can the transformer be a constant ? is it thread safe ?
                 final Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
@@ -268,7 +286,7 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
 
     public static String toString(final Element xml) {
         try {
-            final Transformer transformer = TransformerFactory.newInstance().newTransformer();
+            final Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
 
             final StreamResult result = new StreamResult(new StringWriter());
@@ -276,19 +294,8 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
             transformer.transform(source, result);
 
             return result.getWriter().toString();
-        } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
-            throw new RuntimeException("Unable to serialize xml element " + xml, e);
-        }
-    }
-
-    abstract void endNode(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException;
-
-    @Override
-    public final void endNode() throws IOException {
-        try {
-            endNode(writer);
-        } catch (XMLStreamException e) {
-            throw new IOException("Failed to end element", e);
+        } catch (IllegalArgumentException | TransformerException e) {
+            throw new IllegalStateException("Unable to serialize xml element " + xml, e);
         }
     }