Refactor implementations to hide XMLStreamWriter 71/79771/3
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 16 Jan 2019 15:23:21 +0000 (16:23 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 21 Jan 2019 01:43:37 +0000 (02:43 +0100)
In order to have control over when we output an element, we need
to make sure we know how the writer is being used.

Refactor XMLStreamNormalizedNodeStreamWriter interaction with its
subclasses so we know when we are leaking the writer -- which
happens only in writeValue().

JIRA: YANGTOOLS-927
Change-Id: I7e7bd62016e994a31fe6d69995e9d088746359da
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 127cfbef06dec06721efc4fafe2e9ab551c644e6)

yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemaAwareXMLStreamNormalizedNodeStreamWriter.java
yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemalessXMLStreamNormalizedNodeStreamWriter.java
yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XMLStreamNormalizedNodeStreamWriter.java

index dd0701fc6c0b6bce79dec13c6d0fa063a89dda64..31d44c0a6c6a833fca7f23b580a7f08dc1a48e56 100644 (file)
@@ -11,14 +11,12 @@ package org.opendaylight.yangtools.yang.data.codec.xml;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Map;
-import javax.annotation.Nonnull;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 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.data.api.YangInstanceIdentifier.PathArgument;
-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;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -35,47 +33,42 @@ final class SchemaAwareXMLStreamNormalizedNodeStreamWriter extends XMLStreamNorm
     private final SchemaTracker tracker;
     private final SchemaAwareXMLStreamWriterUtils streamUtils;
 
-    private SchemaAwareXMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer, final SchemaContext context,
+    SchemaAwareXMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer, final SchemaContext context,
                                                            final SchemaPath path) {
         super(writer);
         this.tracker = SchemaTracker.create(context, path);
         this.streamUtils = new SchemaAwareXMLStreamWriterUtils(context);
     }
 
-    static NormalizedNodeStreamWriter newInstance(final XMLStreamWriter writer, final SchemaContext context,
-            final SchemaPath path) {
-        return new SchemaAwareXMLStreamNormalizedNodeStreamWriter(writer, context, path);
-    }
-
     @Override
-    protected void writeValue(final XMLStreamWriter xmlWriter, final QName qname, @Nonnull final Object value,
+    void writeValue(final XMLStreamWriter xmlWriter, final QName qname, final Object value,
             final SchemaNode schemaNode) throws IOException, XMLStreamException {
         streamUtils.writeValue(xmlWriter, schemaNode, value, qname.getModule());
     }
 
     @Override
-    protected void startList(final NodeIdentifier name) {
+    void startList(final NodeIdentifier name) {
         tracker.startList(name);
     }
 
     @Override
-    protected void startListItem(final PathArgument name) throws IOException {
+    void startListItem(final PathArgument name) throws IOException {
         tracker.startListItem(name);
         startElement(name.getNodeType());
     }
 
     @Override
-    protected void endNode(final XMLStreamWriter xmlWriter) throws IOException, XMLStreamException {
+    public void endNode() throws IOException {
         final Object schema = tracker.endNode();
         if (schema instanceof ListSchemaNode) {
             // For lists, we only emit end element on the inner frame
             final Object parent = tracker.getParent();
             if (parent == schema) {
-                xmlWriter.writeEndElement();
+                endElement();
             }
         } else if (schema instanceof ContainerSchemaNode) {
             // Emit container end element
-            xmlWriter.writeEndElement();
+            endElement();
         }
     }
 
index 946018319c9f18457e70f2a169bb9b65f77bbabf..8cbe0d2d664121c4e324fa62abb2140771069e55 100644 (file)
@@ -12,14 +12,12 @@ import java.util.ArrayDeque;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.Map;
-import javax.annotation.Nonnull;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 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.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 
 final class SchemalessXMLStreamNormalizedNodeStreamWriter extends XMLStreamNormalizedNodeStreamWriter<Object> {
     private enum ContainerType {
@@ -34,14 +32,10 @@ final class SchemalessXMLStreamNormalizedNodeStreamWriter extends XMLStreamNorma
 
     private final Deque<ContainerType> containerTypeStack = new ArrayDeque<>();
 
-    private SchemalessXMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer) {
+    SchemalessXMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer) {
         super(writer);
     }
 
-    static NormalizedNodeStreamWriter newInstance(final XMLStreamWriter writer) {
-        return new SchemalessXMLStreamNormalizedNodeStreamWriter(writer);
-    }
-
     @Override
     public void leafNode(final NodeIdentifier name, final Object value, final Map<QName, String> attributes)
             throws IOException {
@@ -102,30 +96,30 @@ final class SchemalessXMLStreamNormalizedNodeStreamWriter extends XMLStreamNorma
     }
 
     @Override
-    protected void writeValue(final XMLStreamWriter xmlWriter, final QName qname, @Nonnull final Object value,
-            final Object context) throws XMLStreamException {
+    void writeValue(final XMLStreamWriter xmlWriter, final QName qname, final Object value, final Object context)
+            throws XMLStreamException {
         xmlWriter.writeCharacters(value.toString());
     }
 
     @Override
-    protected void startList(final NodeIdentifier name) {
+    void startList(final NodeIdentifier name) {
         containerTypeStack.push(ContainerType.LIST);
     }
 
     @Override
-    protected void startListItem(final PathArgument name) throws IOException {
+    void startListItem(final PathArgument name) throws IOException {
         containerTypeStack.push(ContainerType.LIST_ITEM);
         startElement(name.getNodeType());
     }
 
     @Override
-    protected void endNode(final XMLStreamWriter xmlWriter) throws IOException, XMLStreamException {
+    public void endNode() throws IOException {
         ContainerType type = containerTypeStack.pop();
         switch (type) {
             case CONTAINER:
             case LIST_ITEM:
             case ANY_XML:
-                xmlWriter.writeEndElement();
+                endElement();
                 break;
             default:
                 break;
index 44c1fd216ccc26157609c4d8c25eb16df7a21b21..55e4e93b243bd439326b77b7bd459e2e308aa9b3 100644 (file)
@@ -18,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;
@@ -32,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;
@@ -74,8 +74,8 @@ 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 = requireNonNull(writer);
@@ -102,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);
     }
 
     /**
@@ -115,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(XMLStreamWriter xmlWriter, QName qname, @Nonnull Object value, T context)
+    abstract void writeValue(@NonNull XMLStreamWriter xmlWriter, QName qname, @NonNull Object value, T context)
             throws IOException, XMLStreamException;
 
     abstract void startList(NodeIdentifier name);
 
     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();
@@ -177,12 +177,14 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
         }
     }
 
-    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);
             }
@@ -192,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) {
@@ -200,7 +202,15 @@ 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) {
             checkArgument(value instanceof DOMSource, "AnyXML value must be DOMSource, not %s", value);
             final DOMSource domSource = (DOMSource) value;
@@ -289,17 +299,6 @@ public abstract class XMLStreamNormalizedNodeStreamWriter<T> implements Normaliz
         }
     }
 
-    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);
-        }
-    }
-
     @Override
     public final void close() throws IOException {
         try {