+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netconf.sal.streams.listeners;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.restconf.Draft18.MonitoringModule;
+import org.opendaylight.restconf.handlers.SchemaContextHandler;
+import org.opendaylight.restconf.handlers.TransactionChainHandler;
+import org.opendaylight.restconf.parser.IdentifierCodec;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+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.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Abstract class for processing and preparing data
+ *
+ */
+abstract class AbstractNotificationsData {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractNotificationsData.class);
+
+ private TransactionChainHandler transactionChainHandler;
+ private SchemaContextHandler schemaHandler;
+ private String localName;
+
+ /**
+ * Transaction chain for delete data in DS on close()
+ *
+ * @param transactionChainHandler
+ * - creating new write transaction for delete data on close
+ * @param schemaHandler
+ * - for getting schema to deserialize
+ * {@link MonitoringModule#PATH_TO_STREAM_WITHOUT_KEY} to
+ * {@link YangInstanceIdentifier}
+ */
+ public void setCloseVars(final TransactionChainHandler transactionChainHandler,
+ final SchemaContextHandler schemaHandler) {
+ this.transactionChainHandler = transactionChainHandler;
+ this.schemaHandler = schemaHandler;
+ }
+
+ /**
+ * Delete data in DS
+ */
+ protected void deleteDataInDS() throws Exception {
+ final DOMDataWriteTransaction wTx = this.transactionChainHandler.get().newWriteOnlyTransaction();
+ wTx.delete(LogicalDatastoreType.OPERATIONAL, IdentifierCodec
+ .deserialize(MonitoringModule.PATH_TO_STREAM_WITHOUT_KEY + this.localName, this.schemaHandler.get()));
+ wTx.submit().checkedGet();
+ }
+
+ /**
+ * Set localName of last path element of specific listener
+ *
+ * @param localName
+ * - local name
+ */
+ protected void setLocalNameOfPath(final String localName) {
+ this.localName = localName;
+ }
+
+ /**
+ * Formats data specified by RFC3339.
+ *
+ * @param d
+ * Date
+ * @return Data specified by RFC3339.
+ */
+ protected static String toRFC3339(final Date d) {
+ return ListenersConstants.RFC3339_PATTERN.matcher(ListenersConstants.RFC3339.format(d)).replaceAll("$1:$2");
+ }
+
+ /**
+ * Creates {@link Document} document.
+ *
+ * @return {@link Document} document.
+ */
+ protected static Document createDocument() {
+ final DocumentBuilder bob;
+ try {
+ bob = ListenersConstants.DBF.newDocumentBuilder();
+ } catch (final ParserConfigurationException e) {
+ return null;
+ }
+ return bob.newDocument();
+ }
+
+ /**
+ * Write normalized node to {@link DOMResult}
+ *
+ * @param normalized
+ * - data
+ * @param context
+ * - actual schema context
+ * @param schemaPath
+ * - schema path of data
+ * @return {@link DOMResult}
+ */
+ protected DOMResult writeNormalizedNode(final NormalizedNode<?, ?> normalized, final SchemaContext context,
+ final SchemaPath schemaPath) throws IOException, XMLStreamException {
+ final XMLOutputFactory XML_FACTORY = XMLOutputFactory.newFactory();
+ final Document doc = XmlDocumentUtils.getDocument();
+ final DOMResult result = new DOMResult(doc);
+ NormalizedNodeWriter normalizedNodeWriter = null;
+ NormalizedNodeStreamWriter normalizedNodeStreamWriter = null;
+ XMLStreamWriter writer = null;
+
+ try {
+ writer = XML_FACTORY.createXMLStreamWriter(result);
+ normalizedNodeStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(writer, context, schemaPath);
+ normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(normalizedNodeStreamWriter);
+
+ normalizedNodeWriter.write(normalized);
+
+ normalizedNodeWriter.flush();
+ } finally {
+ if (normalizedNodeWriter != null) {
+ normalizedNodeWriter.close();
+ }
+ if (normalizedNodeStreamWriter != null) {
+ normalizedNodeStreamWriter.close();
+ }
+ if (writer != null) {
+ writer.close();
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Generating base element of every notification
+ *
+ * @param doc
+ * - base {@link Document}
+ * @return element of {@link Document}
+ */
+ protected Element basePartDoc(final Document doc) {
+ final Element notificationElement =
+ doc.createElementNS("urn:ietf:params:xml:ns:netconf:notification:1.0", "notification");
+
+ doc.appendChild(notificationElement);
+
+ final Element eventTimeElement = doc.createElement("eventTime");
+ eventTimeElement.setTextContent(toRFC3339(new Date()));
+ notificationElement.appendChild(eventTimeElement);
+
+ return notificationElement;
+ }
+
+ /**
+ * Generating of {@link Document} transforming to string
+ *
+ * @param doc
+ * - {@link Document} with data
+ * @return - string from {@link Document}
+ */
+ protected String transformDoc(final Document doc) {
+ try {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final Transformer transformer = ListenersConstants.FACTORY.newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+ transformer.transform(new DOMSource(doc),
+ new StreamResult(new OutputStreamWriter(out, StandardCharsets.UTF_8)));
+ final byte[] charData = out.toByteArray();
+ return new String(charData, "UTF-8");
+ } catch (TransformerException | UnsupportedEncodingException e) {
+ final String msg = "Error during transformation of Document into String";
+ LOG.error(msg, e);
+ return msg;
+ }
+ }
+}