netconf notifications with namespace
[oam/tr069-adapter.git] / mapper / src / main / java / org / commscope / tr069adapter / mapper / netconf / NetConfNotificationSender.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.mapper.netconf;\r
20 \r
21 import java.io.StringWriter;\r
22 import java.text.SimpleDateFormat;\r
23 import java.util.ArrayList;\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 import javax.xml.parsers.DocumentBuilder;\r
30 import javax.xml.parsers.DocumentBuilderFactory;\r
31 import javax.xml.parsers.ParserConfigurationException;\r
32 import javax.xml.transform.Transformer;\r
33 import javax.xml.transform.TransformerFactory;\r
34 import javax.xml.transform.dom.DOMSource;\r
35 import javax.xml.transform.stream.StreamResult;\r
36 import org.commscope.tr069adapter.acs.common.DeviceInform;\r
37 import org.commscope.tr069adapter.acs.common.ParameterDTO;\r
38 import org.commscope.tr069adapter.mapper.MOMetaData;\r
39 import org.commscope.tr069adapter.mapper.MapperConfigProperties;\r
40 import org.commscope.tr069adapter.mapper.model.NetConfNotificationDTO;\r
41 import org.commscope.tr069adapter.mapper.util.MOMetaDataUtil;\r
42 import org.slf4j.Logger;\r
43 import org.slf4j.LoggerFactory;\r
44 import org.springframework.beans.factory.annotation.Autowired;\r
45 import org.springframework.http.ResponseEntity;\r
46 import org.springframework.stereotype.Component;\r
47 import org.springframework.web.client.RestTemplate;\r
48 import org.w3c.dom.Document;\r
49 import org.w3c.dom.Element;\r
50 \r
51 @Component\r
52 public class NetConfNotificationSender {\r
53 \r
54   private static final Logger LOG = LoggerFactory.getLogger(NetConfNotificationSender.class);\r
55   private static final String BOOLEAN_TRUE_VALUE = "1";\r
56   private static final String BOOLEAN_FALSE_VALUE = "0";\r
57   private static final String BOOLEAN_DATA_TYPE = "boolean";\r
58   public static final String NOTIFICATION_ELEMENT_NAME = "notification";\r
59   public static final String EVENT_TIME = "eventTime";\r
60   private static final String INDEX_STR = "index";\r
61   private static final String INDEX_REGEX = "[0-9]{1,}";\r
62 \r
63 \r
64   @Autowired\r
65   MapperConfigProperties config;\r
66 \r
67   @Autowired\r
68   MOMetaDataUtil metaDataUtil;\r
69 \r
70   @Autowired\r
71   RestTemplate restTemplate;\r
72 \r
73   public ResponseEntity sendNotification(DeviceInform deviceInform) {\r
74     ResponseEntity response = null;\r
75     final String uri = getUri();\r
76     LOG.debug("Posting notification to netconf server {}", uri);\r
77 \r
78     try {\r
79       LOG.debug("deviceInform : {} {}", deviceInform.getInformTypeList(),\r
80           deviceInform.getParameters());\r
81       List<ParameterDTO> parameters = new ArrayList<>();\r
82       for (ParameterDTO parameterDTO : deviceInform.getParameters()) {\r
83         parameters.add(parameterDTO);\r
84       }\r
85 \r
86       convertTR069ToNetConfParams(parameters, deviceInform.getDeviceDetails().getSoftwareVersion(),\r
87           deviceInform.getDeviceDetails().getHardwareVersion());\r
88 \r
89       String nameSpace = metaDataUtil.getMetaDataByTR69Name(deviceInform.getInformType().toString(),\r
90           deviceInform.getDeviceDetails().getSoftwareVersion(),\r
91           deviceInform.getDeviceDetails().getHardwareVersion()).getURI();\r
92 \r
93       String notificationXml =\r
94           getNetconfResponseXML(parameters, deviceInform.getInformType().toString(), nameSpace);\r
95       NetConfNotificationDTO netConfDTO = new NetConfNotificationDTO(\r
96           deviceInform.getDeviceDetails().getDeviceId(), notificationXml);\r
97 \r
98       LOG.debug("Posting notification to netconf server");\r
99       response = restTemplate.postForObject(uri, netConfDTO, ResponseEntity.class);\r
100       LOG.debug("Posting notification to netconf server completed ");\r
101     } catch (Exception e) {\r
102       LOG.error("Exception while sending the notification.", e);\r
103     }\r
104     return response;\r
105   }\r
106 \r
107   public ResponseEntity sendCustomNotification(String deviceId, List<ParameterDTO> parameters,\r
108       String nameSpace) {\r
109     ResponseEntity response = null;\r
110     final String uri = getUri();\r
111     LOG.debug("Posting custom notification to netconf server " + uri);\r
112     try {\r
113       String notificationXml = getNetconfResponseXML(parameters, null, nameSpace);\r
114       NetConfNotificationDTO netConfDTO = new NetConfNotificationDTO(deviceId, notificationXml);\r
115 \r
116       response = restTemplate.postForObject(uri, netConfDTO, ResponseEntity.class);\r
117       LOG.debug("Posting custom notification to netconf server sucessfull");\r
118     } catch (Exception e) {\r
119       LOG.error("Exception while sending the custom notification.", e.toString());\r
120     }\r
121     return response;\r
122   }\r
123 \r
124   private void convertTR069ToNetConfParams(List<ParameterDTO> parameters, String swVersion,\r
125       String hwVersion) {\r
126     List<ParameterDTO> removeList = new ArrayList<>();\r
127     if (null != parameters) {\r
128       for (ParameterDTO param : parameters) {\r
129         if (param.getParamValue() == null || param.getParamValue().trim().length() <= 0) {\r
130           removeList.add(param);\r
131           continue;\r
132         }\r
133         handleBooleanParameters(param, swVersion, hwVersion);\r
134         if (null != param.getParamName()) {\r
135           String netConfMOName = metaDataUtil\r
136               .getNetconfNameByTR69NameWithIndexes(param.getParamName(), swVersion, hwVersion);\r
137           if (null != netConfMOName)\r
138             param.setParamName(netConfMOName);\r
139           else\r
140             removeList.add(param); // unknown parameter found.\r
141         }\r
142       }\r
143       parameters.removeAll(removeList);\r
144     }\r
145   }\r
146 \r
147   private void handleBooleanParameters(ParameterDTO param, String swVersion, String hwVersion) {\r
148     MOMetaData metaData =\r
149         metaDataUtil.getMetaDataByTR69Name(param.getParamName(), swVersion, hwVersion);\r
150     if (null != metaData && BOOLEAN_DATA_TYPE.equalsIgnoreCase(metaData.getDataType())) {\r
151       if (BOOLEAN_TRUE_VALUE.equalsIgnoreCase(param.getParamValue().trim())) {\r
152         param.setParamValue(Boolean.TRUE.toString());\r
153       } else if (BOOLEAN_FALSE_VALUE.equalsIgnoreCase(param.getParamValue().trim())) {\r
154         param.setParamValue(Boolean.FALSE.toString());\r
155       }\r
156     }\r
157   }\r
158 \r
159   private String getUri() {\r
160     return config.getNbiNotificationUri();\r
161   }\r
162 \r
163   private static String getNetconfResponseXML(List<ParameterDTO> parameters,\r
164       String notificationType, String nameSpace) {\r
165     if (parameters == null || parameters.isEmpty()) {\r
166       LOG.debug("There are no parameters found in the response.");\r
167       return null;\r
168     }\r
169 \r
170     String result = null;\r
171     try {\r
172       DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();\r
173       DocumentBuilder docBuilder = docFactory.newDocumentBuilder();\r
174       Document doc = docBuilder.newDocument();\r
175 \r
176       Map<String, Element> parentNodeMap = new HashMap<>();\r
177       Element dataNode = null; // root of all nodes\r
178 \r
179       for (ParameterDTO paramDto : parameters) {\r
180         String paramName = paramDto.getParamName();\r
181         String paramValue = paramDto.getParamValue();\r
182         StringTokenizer tokenizer = new StringTokenizer(paramName, ".");\r
183         String parentNodeName = null;\r
184         String parentNodeKey = null;\r
185         Element parentNode = null;\r
186         while (tokenizer.hasMoreElements()) {\r
187           String nodeName = (String) tokenizer.nextElement();\r
188           if (null == parentNodeName) { // construct first node or\r
189                                         // Device node\r
190             parentNodeName = nodeName;\r
191             parentNodeKey = nodeName;\r
192             // check if the node already exists in parentNodeMap\r
193             parentNode = parentNodeMap.get(parentNodeKey);\r
194             if (null == dataNode) {\r
195               dataNode = parentNode;\r
196             }\r
197             continue;\r
198           } else if (nodeName.matches(INDEX_REGEX)) { // construct\r
199                                                       // tabular and\r
200                                                       // index nodes\r
201 \r
202             // get parent tabular node from parent MAP\r
203             parentNodeKey = parentNodeKey + "." + nodeName;\r
204             Element node = parentNodeMap.get(parentNodeKey);\r
205 \r
206             // create a tabular parent node if doesn't exit in MAP\r
207             if (null == node) {\r
208               node = doc.createElement(parentNodeName);\r
209               parentNodeMap.put(parentNodeKey, node);\r
210 \r
211               // update current tabular parent node.\r
212               if (null != parentNode)\r
213                 parentNode.appendChild(node);\r
214               else\r
215                 parentNode = node;\r
216 \r
217               // prepare and add index node to tabular parent node\r
218               Element indexNode = doc.createElement(INDEX_STR);\r
219               indexNode.setTextContent(nodeName);\r
220               node.appendChild(indexNode);\r
221             }\r
222             parentNode = node; // move parent to child\r
223             parentNodeName = nodeName;\r
224           } else if (parentNodeName.matches(INDEX_REGEX)) { // move to\r
225                                                             // next\r
226                                                             // node\r
227                                                             // if\r
228                                                             // tabular\r
229                                                             // attribute\r
230                                                             // is\r
231                                                             // found\r
232             parentNodeKey = parentNodeKey + "." + nodeName;\r
233             parentNodeName = nodeName;\r
234           } else {\r
235             // construct intermediate nodes\r
236             Element node = parentNodeMap.get(parentNodeKey);\r
237             if (null == node) {\r
238               if (null == dataNode) {\r
239                 node = doc.createElementNS(nameSpace, parentNodeName);\r
240                 dataNode = node;\r
241               } else {\r
242                 node = doc.createElement(parentNodeName);\r
243               }\r
244               parentNodeMap.put(parentNodeKey, node);\r
245               if (null != parentNode)\r
246                 parentNode.appendChild(node);\r
247             }\r
248             parentNodeKey = parentNodeKey + "." + nodeName;\r
249             parentNodeName = nodeName;\r
250             parentNode = node;\r
251           }\r
252         }\r
253         // construct leaf node\r
254         Element leafNode = doc.createElement(parentNodeName);\r
255         leafNode.setTextContent(paramValue);\r
256         parentNode.appendChild(leafNode);\r
257       }\r
258 \r
259       if (null != dataNode) {\r
260         final Element element = doc.createElement(NOTIFICATION_ELEMENT_NAME);\r
261         final Element eventTime = doc.createElement(EVENT_TIME);\r
262         eventTime\r
263             .setTextContent(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));\r
264         element.appendChild(element.getOwnerDocument().importNode(eventTime, true));\r
265 \r
266         if (notificationType != null) {\r
267           final Element evtTypeElement = doc.createElementNS(nameSpace, notificationType);\r
268           evtTypeElement.appendChild(dataNode);\r
269           element.appendChild(element.getOwnerDocument().importNode(evtTypeElement, true));\r
270         } else {\r
271           element.appendChild(element.getOwnerDocument().importNode(dataNode, true));\r
272         }\r
273 \r
274         result = convertDocumentToString(element);\r
275       }\r
276     } catch (ParserConfigurationException pce) {\r
277       LOG.error("Exception while converting the notification: {}", pce.getMessage());\r
278     }\r
279 \r
280     return result;\r
281   }\r
282 \r
283   public static String convertDocumentToString(Element element) {\r
284     String strxml = null;\r
285     try {\r
286       TransformerFactory transformerFactory = TransformerFactory.newInstance();\r
287       Transformer transformer = transformerFactory.newTransformer();\r
288       DOMSource source = new DOMSource(element);\r
289       StreamResult result = new StreamResult(new StringWriter());\r
290       transformer.transform(source, result);\r
291       strxml = result.getWriter().toString();\r
292     } catch (Exception e) {\r
293       LOG.error("Error while converting Element to String" + e);\r
294     }\r
295     LOG.debug("Converted XML is : {}", strxml);\r
296     return strxml;\r
297   }\r
298 }\r