Initial source code
[oam/tr069-adapter.git] / netconf-server / src / main / java / org / commscope / tr069adapter / netconf / notification / NetConfSessionUtil.java
1 /*\r
2  * ============LICENSE_START========================================================================\r
3  * ONAP : tr-069-adapter\r
4  * =================================================================================================\r
5  * Copyright (C) 2020 CommScope Inc Intellectual Property.\r
6  * =================================================================================================\r
7  * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,\r
8  * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You\r
9  * may obtain a copy of the License at\r
10  *\r
11  * http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
14  * either express or implied. See the License for the specific language governing permissions and\r
15  * limitations under the License.\r
16  * ===============LICENSE_END=======================================================================\r
17  */\r
18 \r
19 package org.commscope.tr069adapter.netconf.notification;\r
20 \r
21 import java.io.IOException;\r
22 import java.io.StringWriter;\r
23 import java.text.SimpleDateFormat;\r
24 import java.util.Date;\r
25 import java.util.HashMap;\r
26 import java.util.List;\r
27 import java.util.Map;\r
28 import java.util.StringTokenizer;\r
29 \r
30 import javax.xml.XMLConstants;\r
31 import javax.xml.parsers.DocumentBuilder;\r
32 import javax.xml.parsers.DocumentBuilderFactory;\r
33 import javax.xml.parsers.ParserConfigurationException;\r
34 import javax.xml.transform.Transformer;\r
35 import javax.xml.transform.TransformerFactory;\r
36 import javax.xml.transform.dom.DOMSource;\r
37 import javax.xml.transform.stream.StreamResult;\r
38 \r
39 import org.commscope.tr069adapter.acs.common.DeviceInform;\r
40 import org.commscope.tr069adapter.acs.common.ParameterDTO;\r
41 import org.commscope.tr069adapter.netconf.rpc.CreateSubscription;\r
42 import org.opendaylight.netconf.api.NetconfMessage;\r
43 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;\r
44 import org.opendaylight.netconf.api.xml.XmlUtil;\r
45 import org.slf4j.Logger;\r
46 import org.slf4j.LoggerFactory;\r
47 import org.springframework.stereotype.Component;\r
48 import org.w3c.dom.Document;\r
49 import org.w3c.dom.Element;\r
50 import org.xml.sax.SAXException;\r
51 \r
52 @Component\r
53 public class NetConfSessionUtil {\r
54 \r
55   private static final Logger LOG = LoggerFactory.getLogger(NetConfSessionUtil.class);\r
56 \r
57   private static final String INDEX_STR = "index";\r
58   private static final String INDEX_REGEX = "[0-9]{1,}";\r
59   private static final String NS_URI = "urn:onf:otcc:wireless:yang:tr069-notification";\r
60 \r
61   public void sendNetConfNotification(DeviceInform notification) {\r
62     NetconfMessage netconfMessage = convertToNetConfMessage(notification);\r
63     LOG.debug("Notification converted to NetConf format {}", netconfMessage);\r
64     CreateSubscription.sendNotification(netconfMessage,\r
65         notification.getDeviceDetails().getDeviceId());\r
66   }\r
67 \r
68   private NetconfMessage convertToNetConfMessage(DeviceInform notification) {\r
69     try {\r
70       String netConfXmlMsg = getNetconfResponseXML(notification);\r
71       if (netConfXmlMsg == null)\r
72         throw new IllegalArgumentException("There are no parameters found in the response");\r
73       return new NetconfMessage(XmlUtil.readXmlToDocument(netConfXmlMsg));\r
74     } catch (SAXException | IOException e) {\r
75       throw new IllegalArgumentException("Cannot parse notifications", e);\r
76     }\r
77   }\r
78 \r
79   private static String getNetconfResponseXML(DeviceInform notification) {\r
80     if (notification == null || notification.getParameters().isEmpty()) {\r
81       LOG.debug("There are no parameters found in the response.");\r
82       return null;\r
83     }\r
84 \r
85     List<ParameterDTO> parameters = notification.getParameters();\r
86 \r
87     String result = null;\r
88     try {\r
89       DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();\r
90       docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");\r
91       docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");\r
92       DocumentBuilder docBuilder = docFactory.newDocumentBuilder();\r
93       Document doc = docBuilder.newDocument();\r
94 \r
95       Map<String, Element> parentNodeMap = new HashMap<>();\r
96       Element dataNode = null; // root of all nodes\r
97 \r
98       for (ParameterDTO paramDto : parameters) {\r
99         String paramName = paramDto.getParamName();\r
100         String paramValue = paramDto.getParamValue();\r
101         StringTokenizer tokenizer = new StringTokenizer(paramName, ".");\r
102         String parentNodeName = null;\r
103         StringBuilder parentNodeKey = null;\r
104         Element parentNode = null;\r
105         while (tokenizer.hasMoreElements()) {\r
106           String nodeName = (String) tokenizer.nextElement();\r
107           if (null == parentNodeName) { // construct first node or\r
108                                         // Device node\r
109             parentNodeName = nodeName;\r
110             parentNodeKey = new StringBuilder(nodeName);\r
111             // check if the node already exists in parentNodeMap\r
112             parentNode = parentNodeMap.get(parentNodeKey.toString());\r
113             if (null == dataNode) {\r
114               dataNode = parentNode;\r
115             }\r
116           } else if (nodeName.matches(INDEX_REGEX)) { // construct\r
117                                                       // tabular and\r
118                                                       // index nodes\r
119 \r
120             // get parent tabular node from parent MAP\r
121             parentNodeKey = parentNodeKey.append(".").append(nodeName);\r
122             Element node = parentNodeMap.get(parentNodeKey.toString());\r
123 \r
124             // create a tabular parent node if doesn't exit in MAP\r
125             if (null == node) {\r
126               node = doc.createElement(parentNodeName);\r
127               parentNodeMap.put(parentNodeKey.toString(), node);\r
128 \r
129               // update current tabular parent node.\r
130               if (null != parentNode)\r
131                 parentNode.appendChild(node);\r
132 \r
133               // prepare and add index node to tabular parent node\r
134               Element indexNode = doc.createElement(INDEX_STR);\r
135               indexNode.setTextContent(nodeName);\r
136               node.appendChild(indexNode);\r
137             }\r
138             parentNode = node; // move parent to child\r
139             parentNodeName = nodeName;\r
140           } else if (parentNodeName.matches(INDEX_REGEX)) { // move to\r
141                                                             // next\r
142                                                             // node\r
143                                                             // if\r
144                                                             // tabular\r
145                                                             // attribute\r
146                                                             // is\r
147                                                             // found\r
148             parentNodeKey = parentNodeKey.append(".").append(nodeName);\r
149             parentNodeName = nodeName;\r
150           } else {\r
151             // construct intermediate nodes\r
152             Element node = parentNodeMap.get(parentNodeKey.toString());\r
153             if (null == node) {\r
154               if (null == dataNode) {\r
155                 node = doc.createElementNS(NS_URI, parentNodeName);\r
156                 dataNode = node;\r
157               } else {\r
158                 node = doc.createElement(parentNodeName);\r
159               }\r
160               parentNodeMap.put(parentNodeKey.toString(), node);\r
161               if (null != parentNode)\r
162                 parentNode.appendChild(node);\r
163             }\r
164             parentNodeKey = parentNodeKey.append(".").append(nodeName);\r
165             parentNodeName = nodeName;\r
166             parentNode = node;\r
167           }\r
168         }\r
169         // construct leaf node\r
170         Element leafNode = doc.createElement(parentNodeName);\r
171         leafNode.setTextContent(paramValue);\r
172         if (null != parentNode)\r
173           parentNode.appendChild(leafNode);\r
174       }\r
175 \r
176       if (null != dataNode) {\r
177         final Element element = doc.createElement(XmlNetconfConstants.NOTIFICATION_ELEMENT_NAME);\r
178         final Element eventTime = doc.createElement(XmlNetconfConstants.EVENT_TIME);\r
179         eventTime\r
180             .setTextContent(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));\r
181 \r
182         final Element evtTypeElement =\r
183             doc.createElementNS(NS_URI, notification.getInformTypeList().get(0).toString());\r
184         evtTypeElement.appendChild(dataNode);\r
185         element.appendChild(element.getOwnerDocument().importNode(eventTime, true));\r
186         element.appendChild(element.getOwnerDocument().importNode(evtTypeElement, true));\r
187         result = convertDocumentToString(element);\r
188       }\r
189     } catch (ParserConfigurationException pce) {\r
190       LOG.error("Error while getNetconfResponseXML {}", pce.toString());\r
191     }\r
192 \r
193     return result;\r
194   }\r
195 \r
196   public static String convertDocumentToString(Element element) {\r
197     String strxml = null;\r
198     try {\r
199       TransformerFactory transformerFactory = TransformerFactory.newInstance();\r
200       transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");\r
201       transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");\r
202       Transformer transformer = transformerFactory.newTransformer();\r
203       DOMSource source = new DOMSource(element);\r
204       StreamResult result = new StreamResult(new StringWriter());\r
205       transformer.transform(source, result);\r
206       strxml = result.getWriter().toString();\r
207     } catch (Exception e) {\r
208       LOG.error("Error while converting Element to String {}", e.toString());\r
209     }\r
210     LOG.debug("Converted XML is : {}", strxml);\r
211     return strxml;\r
212   }\r
213 \r
214 }\r