From dddb4925333fa0cea58c24c1516c542ed28fde2f Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 16 Jan 2019 16:23:21 +0100 Subject: [PATCH] Refactor implementations to hide XMLStreamWriter 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 (cherry picked from commit 127cfbef06dec06721efc4fafe2e9ab551c644e6) --- ...reXMLStreamNormalizedNodeStreamWriter.java | 21 +++------ ...ssXMLStreamNormalizedNodeStreamWriter.java | 20 +++----- .../XMLStreamNormalizedNodeStreamWriter.java | 47 +++++++++---------- 3 files changed, 37 insertions(+), 51 deletions(-) diff --git a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemaAwareXMLStreamNormalizedNodeStreamWriter.java b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemaAwareXMLStreamNormalizedNodeStreamWriter.java index dd0701fc6c..31d44c0a6c 100644 --- a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemaAwareXMLStreamNormalizedNodeStreamWriter.java +++ b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemaAwareXMLStreamNormalizedNodeStreamWriter.java @@ -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(); } } diff --git a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemalessXMLStreamNormalizedNodeStreamWriter.java b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemalessXMLStreamNormalizedNodeStreamWriter.java index 946018319c..8cbe0d2d66 100644 --- a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemalessXMLStreamNormalizedNodeStreamWriter.java +++ b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/SchemalessXMLStreamNormalizedNodeStreamWriter.java @@ -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 { private enum ContainerType { @@ -34,14 +32,10 @@ final class SchemalessXMLStreamNormalizedNodeStreamWriter extends XMLStreamNorma private final Deque 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 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; diff --git a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XMLStreamNormalizedNodeStreamWriter.java b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XMLStreamNormalizedNodeStreamWriter.java index 44c1fd216c..55e4e93b24 100644 --- a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XMLStreamNormalizedNodeStreamWriter.java +++ b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XMLStreamNormalizedNodeStreamWriter.java @@ -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 implements Normaliz private static final Set 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 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 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 attributes) throws IOException { + private void writeAttributes(final @NonNull Map attributes) throws IOException { for (final Entry entry : attributes.entrySet()) { try { final QName qname = entry.getKey(); @@ -177,12 +177,14 @@ public abstract class XMLStreamNormalizedNodeStreamWriter implements Normaliz } } - void writeElement(final QName qname, final Object value, @Nullable final Map attributes, + final void writeElement(final QName qname, final Object value, final @Nullable Map 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 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 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 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 { -- 2.36.6