Remove AbstractNotificationsData.writeNormalizedNode()
[netconf.git] / restconf / restconf-nb / src / main / java / org / opendaylight / restconf / nb / rfc8040 / 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.restconf.nb.rfc8040.streams.listeners;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.io.ByteArrayOutputStream;
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.transform.OutputKeys;
18 import javax.xml.transform.Transformer;
19 import javax.xml.transform.TransformerException;
20 import javax.xml.transform.TransformerFactory;
21 import javax.xml.transform.dom.DOMSource;
22 import javax.xml.transform.stream.StreamResult;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
26 import org.opendaylight.restconf.nb.rfc8040.Rfc8040;
27 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
28 import org.opendaylight.yangtools.util.xml.UntrustedXML;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.w3c.dom.Document;
33 import org.w3c.dom.Element;
34
35 /**
36  * Abstract class for processing and preparing data.
37  */
38 abstract class AbstractNotificationsData {
39     private static final Logger LOG = LoggerFactory.getLogger(AbstractNotificationsData.class);
40     private static final TransformerFactory TF = TransformerFactory.newInstance();
41
42     private final String localName;
43
44     protected SchemaContextHandler schemaHandler;
45     private DOMDataBroker dataBroker;
46
47     AbstractNotificationsData(final QName lastQName) {
48         localName = lastQName.getLocalName();
49     }
50
51     /**
52      * Data broker for delete data in DS on close().
53      *
54      * @param dataBroker creating new write transaction for delete data on close
55      * @param schemaHandler for formatting notifications
56      */
57     @SuppressWarnings("checkstyle:hiddenField")
58     // FIXME: this is pure lifecycle nightmare just because ...
59     public void setCloseVars(final DOMDataBroker dataBroker, final SchemaContextHandler schemaHandler) {
60         this.dataBroker = dataBroker;
61         this.schemaHandler = schemaHandler;
62     }
63
64     /**
65      * Delete data in DS.
66      */
67     // FIXME: here we touch datastore, which probably should be done by whoever instantiated us or created the resource,
68     //        or they should be giving us the transaction
69     protected ListenableFuture<?> deleteDataInDS() {
70         final DOMDataTreeWriteTransaction wTx = dataBroker.newWriteOnlyTransaction();
71         wTx.delete(LogicalDatastoreType.OPERATIONAL, Rfc8040.restconfStateStreamPath(localName));
72         return wTx.commit();
73     }
74
75     /**
76      * Formats data specified by RFC3339.
77      *
78      * @param now time stamp
79      * @return Data specified by RFC3339.
80      */
81     protected static String toRFC3339(final Instant now) {
82         return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.ofInstant(now, ZoneId.systemDefault()));
83     }
84
85     /**
86      * Creates {@link Document} document.
87      *
88      * @return {@link Document} document.
89      */
90     protected static Document createDocument() {
91         return UntrustedXML.newDocumentBuilder().newDocument();
92     }
93
94     /**
95      * Generating base element of every notification.
96      *
97      * @param doc
98      *            base {@link Document}
99      * @return element of {@link Document}
100      */
101     protected Element basePartDoc(final Document doc) {
102         final var notificationElement = NotificationFormatter.createNotificationElement(doc);
103         doc.appendChild(notificationElement);
104         return notificationElement;
105     }
106
107     /**
108      * Generating of {@link Document} transforming to string.
109      *
110      * @param doc
111      *            {@link Document} with data
112      * @return - string from {@link Document}
113      */
114     protected String transformDoc(final Document doc) {
115         final ByteArrayOutputStream out = new ByteArrayOutputStream();
116
117         try {
118             final Transformer transformer = TF.newTransformer();
119             transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
120             transformer.setOutputProperty(OutputKeys.METHOD, "xml");
121             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
122             transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
123             transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
124             transformer.transform(new DOMSource(doc), new StreamResult(out));
125         } catch (final TransformerException e) {
126             // FIXME: this should raise an exception
127             final String msg = "Error during transformation of Document into String";
128             LOG.error(msg, e);
129             return msg;
130         }
131
132         return new String(out.toByteArray(), StandardCharsets.UTF_8);
133     }
134 }