From 370ab55bc8930fdf70ea5f5443498fa54c7863ba Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 6 Nov 2022 22:49:37 +0100 Subject: [PATCH] Clean up XML interactions We have a chunk of duplicated code, make sure we provide provide utilities. Change-Id: Ibb2b3e14f23c76aa101dcd3766d35aa6a15a5752 Signed-off-by: Robert Varga --- .../listeners/AbstractNotificationsData.java | 9 +--- .../listeners/DataTreeCandidateFormatter.java | 9 +--- .../listeners/NotificationFormatter.java | 51 +++++++++++++++---- .../XMLDataTreeCandidateFormatter.java | 24 ++------- .../listeners/XMLNotificationFormatter.java | 42 ++++++--------- 5 files changed, 61 insertions(+), 74 deletions(-) diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/AbstractNotificationsData.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/AbstractNotificationsData.java index abeaea98a3..b96593465c 100644 --- a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/AbstractNotificationsData.java +++ b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/AbstractNotificationsData.java @@ -153,15 +153,8 @@ abstract class AbstractNotificationsData { * @return element of {@link Document} */ protected Element basePartDoc(final Document doc) { - final Element notificationElement = doc.createElementNS( - NotificationFormatter.NOTIFICATION_NAMESPACE, NotificationFormatter.NOTIFICATION_ELEMENT); - + final var notificationElement = NotificationFormatter.createNotificationElement(doc); doc.appendChild(notificationElement); - - final Element eventTimeElement = doc.createElement("eventTime"); - eventTimeElement.setTextContent(toRFC3339(Instant.now())); - notificationElement.appendChild(eventTimeElement); - return notificationElement; } diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/DataTreeCandidateFormatter.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/DataTreeCandidateFormatter.java index 35ef644b17..9d0b65822a 100644 --- a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/DataTreeCandidateFormatter.java +++ b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/DataTreeCandidateFormatter.java @@ -9,13 +9,10 @@ package org.opendaylight.restconf.nb.rfc8040.streams.listeners; import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.DATA_CHANGED_NOTIFICATION_ELEMENT; import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.DATA_CHANGE_EVENT_ELEMENT; -import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.NOTIFICATION_ELEMENT; -import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.NOTIFICATION_NAMESPACE; import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.SAL_REMOTE_NAMESPACE; import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.XML_OUTPUT_FACTORY; import java.io.IOException; -import java.time.Instant; import java.util.Collection; import java.util.stream.Collectors; import javax.xml.stream.XMLStreamException; @@ -47,11 +44,7 @@ abstract class DataTreeCandidateFormatter extends EventFormatter input) throws IOException { - final Element notificationElement = doc.createElementNS(NOTIFICATION_NAMESPACE, NOTIFICATION_ELEMENT); - final Element eventTimeElement = doc.createElement("eventTime"); - eventTimeElement.setTextContent(toRFC3339(Instant.now())); - notificationElement.appendChild(eventTimeElement); - + final Element notificationElement = NotificationFormatter.createNotificationElement(doc); final Element notificationEventElement = doc.createElementNS( SAL_REMOTE_NAMESPACE, DATA_CHANGED_NOTIFICATION_ELEMENT); diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationFormatter.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationFormatter.java index 13fef7a41e..b864c109a5 100644 --- a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationFormatter.java +++ b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationFormatter.java @@ -8,12 +8,14 @@ package org.opendaylight.restconf.nb.rfc8040.streams.listeners; import java.io.IOException; +import java.io.Writer; import java.time.Instant; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.dom.DOMResult; import javax.xml.xpath.XPathExpressionException; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.dom.api.DOMEvent; import org.opendaylight.mdsal.dom.api.DOMNotification; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.DataChangedNotification; @@ -27,8 +29,8 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; abstract class NotificationFormatter extends EventFormatter { - static final String NOTIFICATION_NAMESPACE = "urn:ietf:params:xml:ns:netconf:notification:1.0"; - static final String NOTIFICATION_ELEMENT = "notification"; + private static final String NOTIFICATION_NAMESPACE = "urn:ietf:params:xml:ns:netconf:notification:1.0"; + private static final String NOTIFICATION_ELEMENT = "notification"; static final String SAL_REMOTE_NAMESPACE = DataChangedNotification.QNAME.getNamespace().toString(); static final String DATA_CHANGED_NOTIFICATION_ELEMENT = DataChangedNotification.QNAME.getLocalName(); @@ -52,15 +54,10 @@ abstract class NotificationFormatter extends EventFormatter { @Override final void fillDocument(final Document doc, final EffectiveModelContext schemaContext, final DOMNotification input) throws IOException { - final Element notificationElement = doc.createElementNS(NOTIFICATION_NAMESPACE, NOTIFICATION_ELEMENT); - final Element eventTimeElement = doc.createElement("eventTime"); - final Instant now = input instanceof DOMEvent domEvent ? domEvent.getEventInstant() : Instant.now(); - eventTimeElement.setTextContent(toRFC3339(now)); - notificationElement.appendChild(eventTimeElement); - - final Element notificationEventElement = doc.createElementNS(SAL_REMOTE_NAMESPACE, - "create-notification-stream"); - final Element dataElement = doc.createElement("notification"); + final var notificationElement = createNotificationElement(doc, + input instanceof DOMEvent domEvent ? domEvent.getEventInstant() : Instant.now()); + final var notificationEventElement = doc.createElementNS(SAL_REMOTE_NAMESPACE, "create-notification-stream"); + final var dataElement = doc.createElement("notification"); final DOMResult result = new DOMResult(dataElement); try { final XMLStreamWriter writer = XML_OUTPUT_FACTORY.createXMLStreamWriter(result); @@ -83,4 +80,36 @@ abstract class NotificationFormatter extends EventFormatter { nodeWriter.write(body); } } + + /** + * Generating base element of every notification. + * + * @param doc base {@link Document} + * @return element of {@link Document} + */ + static @NonNull Element createNotificationElement(final Document doc) { + return createNotificationElement(doc, Instant.now()); + } + + static @NonNull Element createNotificationElement(final Document doc, final Instant now) { + final var notificationElement = doc.createElementNS(NOTIFICATION_NAMESPACE, NOTIFICATION_ELEMENT); + final Element eventTimeElement = doc.createElement("eventTime"); + eventTimeElement.setTextContent(toRFC3339(now)); + notificationElement.appendChild(eventTimeElement); + return notificationElement; + } + + static @NonNull XMLStreamWriter createStreamWriterWithNotification(final Writer writer, final Instant now) + throws XMLStreamException { + final var xmlStreamWriter = XML_OUTPUT_FACTORY.createXMLStreamWriter(writer); + xmlStreamWriter.setDefaultNamespace(NOTIFICATION_NAMESPACE); + + xmlStreamWriter.writeStartElement(NOTIFICATION_NAMESPACE, NOTIFICATION_ELEMENT); + xmlStreamWriter.writeDefaultNamespace(NOTIFICATION_NAMESPACE); + + xmlStreamWriter.writeStartElement("eventTime"); + xmlStreamWriter.writeCharacters(toRFC3339(now)); + xmlStreamWriter.writeEndElement(); + return xmlStreamWriter; + } } diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/XMLDataTreeCandidateFormatter.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/XMLDataTreeCandidateFormatter.java index 1ca5a941ea..b660c12333 100644 --- a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/XMLDataTreeCandidateFormatter.java +++ b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/XMLDataTreeCandidateFormatter.java @@ -8,17 +8,13 @@ package org.opendaylight.restconf.nb.rfc8040.streams.listeners; import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.DATA_CHANGED_NOTIFICATION_ELEMENT; -import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.NOTIFICATION_ELEMENT; -import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.NOTIFICATION_NAMESPACE; import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.SAL_REMOTE_NAMESPACE; -import static org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationFormatter.XML_OUTPUT_FACTORY; import java.io.IOException; import java.io.StringWriter; import java.time.Instant; import java.util.Collection; import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; import javax.xml.xpath.XPathExpressionException; import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; @@ -51,27 +47,16 @@ public final class XMLDataTreeCandidateFormatter extends DataTreeCandidateFormat @Override String createText(final EffectiveModelContext schemaContext, final Collection input, final Instant now, final boolean leafNodesOnly, final boolean skipData) throws Exception { - StringWriter writer = new StringWriter(); + final var writer = new StringWriter(); - final XMLStreamWriter xmlStreamWriter; try { - xmlStreamWriter = XML_OUTPUT_FACTORY.createXMLStreamWriter(writer); - xmlStreamWriter.setDefaultNamespace(NOTIFICATION_NAMESPACE); - - xmlStreamWriter.writeStartElement(NOTIFICATION_NAMESPACE, NOTIFICATION_ELEMENT); - xmlStreamWriter.writeDefaultNamespace(NOTIFICATION_NAMESPACE); - - xmlStreamWriter.writeStartElement("eventTime"); - xmlStreamWriter.writeCharacters(toRFC3339(now)); - xmlStreamWriter.writeEndElement(); + final var xmlStreamWriter = NotificationFormatter.createStreamWriterWithNotification(writer, now); xmlStreamWriter.setDefaultNamespace(SAL_REMOTE_NAMESPACE); xmlStreamWriter.writeStartElement(SAL_REMOTE_NAMESPACE, DATA_CHANGED_NOTIFICATION_ELEMENT); - final XmlDataTreeCandidateSerializer serializer = - new XmlDataTreeCandidateSerializer(schemaContext, xmlStreamWriter); - - for (final DataTreeCandidate candidate : input) { + final var serializer = new XmlDataTreeCandidateSerializer(schemaContext, xmlStreamWriter); + for (var candidate : input) { serializer.serialize(candidate, leafNodesOnly, skipData); } @@ -85,7 +70,6 @@ public final class XMLDataTreeCandidateFormatter extends DataTreeCandidateFormat throw new IOException("Failed to write notification content", e); } - return writer.toString(); } } diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/XMLNotificationFormatter.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/XMLNotificationFormatter.java index 4b0d53ea4c..7b453032b6 100644 --- a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/XMLNotificationFormatter.java +++ b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/XMLNotificationFormatter.java @@ -11,10 +11,8 @@ import java.io.IOException; import java.io.StringWriter; import java.time.Instant; import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; import javax.xml.xpath.XPathExpressionException; import org.opendaylight.mdsal.dom.api.DOMNotification; -import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; @@ -44,36 +42,26 @@ final class XMLNotificationFormatter extends NotificationFormatter { @Override String createText(final EffectiveModelContext schemaContext, final DOMNotification input, final Instant now, - final boolean leafNodesOnly, final boolean skipData) - throws IOException { - final StringWriter writer = new StringWriter(); - try { - final XMLStreamWriter xmlStreamWriter = XML_OUTPUT_FACTORY.createXMLStreamWriter(writer); - xmlStreamWriter.setDefaultNamespace(NOTIFICATION_NAMESPACE); - - xmlStreamWriter.writeStartElement(NOTIFICATION_NAMESPACE, NOTIFICATION_ELEMENT); - xmlStreamWriter.writeDefaultNamespace(NOTIFICATION_NAMESPACE); - - xmlStreamWriter.writeStartElement("eventTime"); - xmlStreamWriter.writeCharacters(toRFC3339(now)); - xmlStreamWriter.writeEndElement(); - - final NormalizedNodeStreamWriter nnStreamWriter = - XMLStreamNormalizedNodeStreamWriter.create(xmlStreamWriter, schemaContext, input.getType()); + final boolean leafNodesOnly, final boolean skipData) throws IOException { + final var writer = new StringWriter(); - final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter); - nnWriter.write(input.getBody()); - nnWriter.flush(); - - xmlStreamWriter.writeEndElement(); - xmlStreamWriter.writeEndDocument(); - xmlStreamWriter.flush(); + try { + final var xmlStreamWriter = NotificationFormatter.createStreamWriterWithNotification(writer, now); + final var nnStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlStreamWriter, schemaContext, + input.getType()); - nnWriter.close(); + try (var nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter)) { + nnWriter.write(input.getBody()); + nnWriter.flush(); - return writer.toString(); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeEndDocument(); + xmlStreamWriter.flush(); + } } catch (XMLStreamException e) { throw new IOException("Failed to write notification content", e); } + + return writer.toString(); } } -- 2.36.6