Switch from config-parent in pom files
[netconf.git] / restconf / sal-rest-connector / src / main / java / org / opendaylight / netconf / sal / streams / listeners / AbstractNotificationsData.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.sal.streams.listeners;
9
10 import java.io.ByteArrayOutputStream;
11 import java.io.IOException;
12 import java.nio.charset.StandardCharsets;
13 import java.time.Instant;
14 import java.time.OffsetDateTime;
15 import java.time.ZoneId;
16 import java.time.format.DateTimeFormatter;
17 import javax.xml.stream.XMLOutputFactory;
18 import javax.xml.stream.XMLStreamException;
19 import javax.xml.stream.XMLStreamWriter;
20 import javax.xml.transform.OutputKeys;
21 import javax.xml.transform.Transformer;
22 import javax.xml.transform.TransformerException;
23 import javax.xml.transform.TransformerFactory;
24 import javax.xml.transform.dom.DOMResult;
25 import javax.xml.transform.dom.DOMSource;
26 import javax.xml.transform.stream.StreamResult;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
29 import org.opendaylight.restconf.Rfc8040.MonitoringModule;
30 import org.opendaylight.restconf.handlers.SchemaContextHandler;
31 import org.opendaylight.restconf.handlers.TransactionChainHandler;
32 import org.opendaylight.restconf.parser.IdentifierCodec;
33 import org.opendaylight.yangtools.util.xml.UntrustedXML;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
37 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
38 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter;
39 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
40 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
41 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.w3c.dom.Document;
45 import org.w3c.dom.Element;
46
47 /**
48  * Abstract class for processing and preparing data.
49  *
50  */
51 abstract class AbstractNotificationsData {
52     private static final Logger LOG = LoggerFactory.getLogger(AbstractNotificationsData.class);
53     private static final TransformerFactory TF = TransformerFactory.newInstance();
54
55     private TransactionChainHandler transactionChainHandler;
56     private SchemaContextHandler schemaHandler;
57     private String localName;
58
59     /**
60      * Transaction chain for delete data in DS on close().
61      *
62      * @param transactionChainHandler
63      *            creating new write transaction for delete data on close
64      * @param schemaHandler
65      *            for getting schema to deserialize
66      *            {@link MonitoringModule#PATH_TO_STREAM_WITHOUT_KEY} to
67      *            {@link YangInstanceIdentifier}
68      */
69     public void setCloseVars(final TransactionChainHandler transactionChainHandler,
70             final SchemaContextHandler schemaHandler) {
71         this.transactionChainHandler = transactionChainHandler;
72         this.schemaHandler = schemaHandler;
73     }
74
75     /**
76      * Delete data in DS.
77      */
78     protected void deleteDataInDS() throws Exception {
79         final DOMDataWriteTransaction wTx = this.transactionChainHandler.get().newWriteOnlyTransaction();
80         wTx.delete(LogicalDatastoreType.OPERATIONAL, IdentifierCodec
81                 .deserialize(MonitoringModule.PATH_TO_STREAM_WITHOUT_KEY + this.localName, this.schemaHandler.get()));
82         wTx.submit().checkedGet();
83     }
84
85     /**
86      * Set localName of last path element of specific listener.
87      *
88      * @param localName
89      *            local name
90      */
91     protected void setLocalNameOfPath(final String localName) {
92         this.localName = localName;
93     }
94
95     /**
96      * Formats data specified by RFC3339.
97      *
98      * @param now time stamp
99      * @return Data specified by RFC3339.
100      */
101     protected static String toRFC3339(final Instant now) {
102         return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.ofInstant(now, ZoneId.systemDefault()));
103     }
104
105     /**
106      * Creates {@link Document} document.
107      *
108      * @return {@link Document} document.
109      */
110     protected static Document createDocument() {
111         return UntrustedXML.newDocumentBuilder().newDocument();
112     }
113
114     /**
115      * Write normalized node to {@link DOMResult}.
116      *
117      * @param normalized
118      *            data
119      * @param context
120      *            actual schema context
121      * @param schemaPath
122      *            schema path of data
123      * @return {@link DOMResult}
124      */
125     protected DOMResult writeNormalizedNode(final NormalizedNode<?, ?> normalized, final SchemaContext context,
126             final SchemaPath schemaPath) throws IOException, XMLStreamException {
127         final XMLOutputFactory xmlFactory = XMLOutputFactory.newFactory();
128         final Document doc = XmlDocumentUtils.getDocument();
129         final DOMResult result = new DOMResult(doc);
130         NormalizedNodeWriter normalizedNodeWriter = null;
131         NormalizedNodeStreamWriter normalizedNodeStreamWriter = null;
132         XMLStreamWriter writer = null;
133
134         try {
135             writer = xmlFactory.createXMLStreamWriter(result);
136             normalizedNodeStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(writer, context, schemaPath);
137             normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(normalizedNodeStreamWriter);
138
139             normalizedNodeWriter.write(normalized);
140
141             normalizedNodeWriter.flush();
142         } finally {
143             if (normalizedNodeWriter != null) {
144                 normalizedNodeWriter.close();
145             }
146             if (normalizedNodeStreamWriter != null) {
147                 normalizedNodeStreamWriter.close();
148             }
149             if (writer != null) {
150                 writer.close();
151             }
152         }
153
154         return result;
155     }
156
157     /**
158      * Generating base element of every notification.
159      *
160      * @param doc
161      *            base {@link Document}
162      * @return element of {@link Document}
163      */
164     protected Element basePartDoc(final Document doc) {
165         final Element notificationElement =
166                 doc.createElementNS("urn:ietf:params:xml:ns:netconf:notification:1.0", "notification");
167
168         doc.appendChild(notificationElement);
169
170         final Element eventTimeElement = doc.createElement("eventTime");
171         eventTimeElement.setTextContent(toRFC3339(Instant.now()));
172         notificationElement.appendChild(eventTimeElement);
173
174         return notificationElement;
175     }
176
177     /**
178      * Generating of {@link Document} transforming to string.
179      *
180      * @param doc
181      *            {@link Document} with data
182      * @return - string from {@link Document}
183      */
184     protected String transformDoc(final Document doc) {
185         final ByteArrayOutputStream out = new ByteArrayOutputStream();
186
187         try {
188             final Transformer transformer = TF.newTransformer();
189             transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
190             transformer.setOutputProperty(OutputKeys.METHOD, "xml");
191             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
192             transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
193             transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
194             transformer.transform(new DOMSource(doc), new StreamResult(out));
195         } catch (TransformerException e) {
196             // FIXME: this should raise an exception
197             final String msg = "Error during transformation of Document into String";
198             LOG.error(msg, e);
199             return msg;
200         }
201
202         return new String(out.toByteArray(), StandardCharsets.UTF_8);
203     }
204 }