2 * ============LICENSE_START========================================================================
3 * ONAP : tr-069-adapter
4 * =================================================================================================
5 * Copyright (C) 2020 CommScope Inc Intellectual Property.
6 * =================================================================================================
7 * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You
9 * may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
14 * either express or implied. See the License for the specific language governing permissions and
15 * limitations under the License.
16 * ===============LICENSE_END=======================================================================
19 package org.commscope.tr069adapter.mapper.netconf;
21 import java.io.StringWriter;
22 import java.text.SimpleDateFormat;
23 import java.util.ArrayList;
24 import java.util.Date;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.StringTokenizer;
30 import javax.xml.XMLConstants;
31 import javax.xml.parsers.DocumentBuilder;
32 import javax.xml.parsers.DocumentBuilderFactory;
33 import javax.xml.parsers.ParserConfigurationException;
34 import javax.xml.transform.Transformer;
35 import javax.xml.transform.TransformerFactory;
36 import javax.xml.transform.dom.DOMSource;
37 import javax.xml.transform.stream.StreamResult;
39 import org.commscope.tr069adapter.acs.common.DeviceInform;
40 import org.commscope.tr069adapter.acs.common.ParameterDTO;
41 import org.commscope.tr069adapter.acs.common.inform.TransferCompleteInform;
42 import org.commscope.tr069adapter.mapper.MOMetaData;
43 import org.commscope.tr069adapter.mapper.MapperConfigProperties;
44 import org.commscope.tr069adapter.mapper.model.NetConfNotificationDTO;
45 import org.commscope.tr069adapter.mapper.util.MOMetaDataUtil;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.http.ResponseEntity;
50 import org.springframework.stereotype.Component;
51 import org.springframework.web.client.RestTemplate;
52 import org.w3c.dom.Document;
53 import org.w3c.dom.Element;
56 public class NetConfNotificationSender {
58 private static final Logger LOG = LoggerFactory.getLogger(NetConfNotificationSender.class);
59 private static final String BOOLEAN_TRUE_VALUE = "1";
60 private static final String BOOLEAN_FALSE_VALUE = "0";
61 private static final String BOOLEAN_DATA_TYPE = "boolean";
62 public static final String NOTIFICATION_ELEMENT_NAME = "notification";
63 public static final String EVENT_TIME = "eventTime";
64 private static final String INDEX_STR = "index";
65 private static final String INDEX_REGEX = "[0-9]{1,}";
69 MapperConfigProperties config;
72 MOMetaDataUtil metaDataUtil;
75 RestTemplate restTemplate;
77 public ResponseEntity sendNotification(DeviceInform deviceInform) {
78 ResponseEntity response = null;
79 final String uri = getUri();
80 LOG.debug("Posting notification to netconf server {}", uri);
83 LOG.debug("deviceInform : {} {}", deviceInform.getInformTypeList(),
84 deviceInform.getParameters());
85 List<ParameterDTO> parameters = new ArrayList<>();
86 for (ParameterDTO parameterDTO : deviceInform.getParameters()) {
87 if (!parameterDTO.getParamName().equalsIgnoreCase("Device.DeviceInfo.SerialNumber"))
88 parameters.add(parameterDTO);
90 parameters.add(new ParameterDTO("Device.DeviceInfo.SerialNumber",
91 deviceInform.getDeviceDetails().getDeviceId()));
93 convertTR069ToNetConfParams(parameters, deviceInform.getDeviceDetails().getSoftwareVersion(),
94 deviceInform.getDeviceDetails().getHardwareVersion());
96 String nameSpace = metaDataUtil.getMetaDataByTR69Name(deviceInform.getInformType().toString(),
97 deviceInform.getDeviceDetails().getSoftwareVersion(),
98 deviceInform.getDeviceDetails().getHardwareVersion()).getURI();
100 String notificationXml =
101 getNetconfResponseXML(parameters, deviceInform.getInformType().toString(), nameSpace);
102 NetConfNotificationDTO netConfDTO = new NetConfNotificationDTO(
103 deviceInform.getDeviceDetails().getDeviceId(), notificationXml);
105 LOG.debug("Posting notification to netconf server");
106 response = restTemplate.postForObject(uri, netConfDTO, ResponseEntity.class);
107 LOG.debug("Posting notification to netconf server completed ");
108 } catch (Exception e) {
109 LOG.error("Exception while sending the notification.", e);
114 public ResponseEntity sendTransferCompleteNotification(TransferCompleteInform tcInform) {
115 ResponseEntity response = null;
116 final String uri = getUri();
117 LOG.debug("Posting notification to netconf server {}", uri);
120 // LOG.debug("deviceInform : {} {}", tcInform.getInformTypeList(),
121 // tcInform.getParameters());
122 // List<ParameterDTO> parameters = new ArrayList<>();
123 // for (ParameterDTO parameterDTO : tcInform.getParameters()) {
124 // parameters.add(parameterDTO);
127 List<ParameterDTO> parameters = new ArrayList<>();
128 parameters.add(new ParameterDTO("command-key", tcInform.getCommandKey()));
129 parameters.add(new ParameterDTO("fault-code", String.valueOf(tcInform.getFaultCode())));
130 parameters.add(new ParameterDTO("fault-string", tcInform.getFaultString()));
131 parameters.add(new ParameterDTO("start-time", tcInform.getStartTime()));
132 parameters.add(new ParameterDTO("complete-time", tcInform.getCompleteTime()));
134 String nameSpace = metaDataUtil.getMetaDataByTR69Name(tcInform.getInformType().toString(),
135 tcInform.getDeviceDetails().getSoftwareVersion(),
136 tcInform.getDeviceDetails().getHardwareVersion()).getURI();
138 String notificationXml =
139 getNetConfReposneXMLForTC(parameters, tcInform.getInformType().toString(), nameSpace);
140 NetConfNotificationDTO netConfDTO =
141 new NetConfNotificationDTO(tcInform.getDeviceDetails().getDeviceId(), notificationXml);
143 LOG.debug("Posting notification to netconf server");
144 response = restTemplate.postForObject(uri, netConfDTO, ResponseEntity.class);
145 LOG.debug("Posting notification to netconf server completed ");
146 } catch (Exception e) {
147 LOG.error("Exception while sending the notification.", e);
152 public ResponseEntity sendCustomNotification(String deviceId, List<ParameterDTO> parameters,
154 ResponseEntity response = null;
155 final String uri = getUri();
156 LOG.debug("Posting custom notification to netconf server {}", uri);
158 String notificationXml = getNetconfResponseXML(parameters, null, nameSpace);
159 NetConfNotificationDTO netConfDTO = new NetConfNotificationDTO(deviceId, notificationXml);
161 response = restTemplate.postForObject(uri, netConfDTO, ResponseEntity.class);
162 LOG.debug("Posting custom notification to netconf server sucessfull");
163 } catch (Exception e) {
164 LOG.error("Exception while sending the custom notification.", e);
169 private void convertTR069ToNetConfParams(List<ParameterDTO> parameters, String swVersion,
171 List<ParameterDTO> removeList = new ArrayList<>();
172 if (null != parameters) {
173 for (ParameterDTO param : parameters) {
174 if (param.getParamValue() == null || param.getParamValue().trim().length() <= 0) {
175 removeList.add(param);
178 handleBooleanParameters(param, swVersion, hwVersion);
179 if (null != param.getParamName()) {
180 String netConfMOName = metaDataUtil
181 .getNetconfNameByTR69NameWithIndexes(param.getParamName(), swVersion, hwVersion);
182 if (null != netConfMOName)
183 param.setParamName(netConfMOName);
185 removeList.add(param); // unknown parameter found.
188 parameters.removeAll(removeList);
192 private void handleBooleanParameters(ParameterDTO param, String swVersion, String hwVersion) {
193 MOMetaData metaData =
194 metaDataUtil.getMetaDataByTR69Name(param.getParamName(), swVersion, hwVersion);
195 if (null != metaData && BOOLEAN_DATA_TYPE.equalsIgnoreCase(metaData.getDataType())) {
196 if (BOOLEAN_TRUE_VALUE.equalsIgnoreCase(param.getParamValue().trim())) {
197 param.setParamValue(Boolean.TRUE.toString());
198 } else if (BOOLEAN_FALSE_VALUE.equalsIgnoreCase(param.getParamValue().trim())) {
199 param.setParamValue(Boolean.FALSE.toString());
204 private String getUri() {
205 return config.getNbiNotificationUri();
208 private static String getNetconfResponseXML(List<ParameterDTO> parameters,
209 String notificationType, String nameSpace) {
210 if (parameters == null || parameters.isEmpty()) {
211 LOG.debug("There are no parameters found in the response.");
215 String result = null;
217 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
218 docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
219 docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
220 DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
221 Document doc = docBuilder.newDocument();
223 Map<String, Element> parentNodeMap = new HashMap<>();
224 Element dataNode = null; // root of all nodes
226 for (ParameterDTO paramDto : parameters) {
227 String paramName = paramDto.getParamName();
228 String paramValue = paramDto.getParamValue();
229 StringTokenizer tokenizer = new StringTokenizer(paramName, ".");
230 String parentNodeName = null;
231 String parentNodeKey = null;
232 Element parentNode = null;
233 while (tokenizer.hasMoreElements()) {
234 String nodeName = (String) tokenizer.nextElement();
235 if (null == parentNodeName) { // construct first node or
237 parentNodeName = nodeName;
238 parentNodeKey = nodeName;
239 // check if the node already exists in parentNodeMap
240 parentNode = parentNodeMap.get(parentNodeKey);
241 if (null == dataNode) {
242 dataNode = parentNode;
245 } else if (nodeName.matches(INDEX_REGEX)) { // construct
249 // get parent tabular node from parent MAP
250 StringBuilder bld = new StringBuilder();
251 bld.append(parentNodeKey);
253 bld.append(nodeName);
254 parentNodeKey = bld.toString();
255 Element node = parentNodeMap.get(parentNodeKey);
257 // create a tabular parent node if doesn't exit in MAP
259 node = doc.createElement(parentNodeName);
260 parentNodeMap.put(parentNodeKey, node);
262 // update current tabular parent node.
263 if (null != parentNode)
264 parentNode.appendChild(node);
268 // prepare and add index node to tabular parent node
269 Element indexNode = doc.createElement(INDEX_STR);
270 indexNode.setTextContent(nodeName);
271 node.appendChild(indexNode);
273 parentNode = node; // move parent to child
274 parentNodeName = nodeName;
275 } else if (parentNodeName.matches(INDEX_REGEX)) { // move to
283 StringBuilder bld = new StringBuilder();
284 bld.append(parentNodeKey);
286 bld.append(nodeName);
287 parentNodeKey = bld.toString();
288 parentNodeName = nodeName;
290 // construct intermediate nodes
291 Element node = parentNodeMap.get(parentNodeKey);
293 if (null == dataNode) {
294 node = doc.createElementNS(nameSpace, parentNodeName);
297 node = doc.createElement(parentNodeName);
299 parentNodeMap.put(parentNodeKey, node);
300 if (null != parentNode)
301 parentNode.appendChild(node);
303 StringBuilder bld = new StringBuilder();
304 bld.append(parentNodeKey);
306 bld.append(nodeName);
307 parentNodeKey = bld.toString();
308 parentNodeName = nodeName;
312 // construct leaf node
313 Element leafNode = doc.createElement(parentNodeName);
314 leafNode.setTextContent(paramValue);
315 if (null != parentNode)
316 parentNode.appendChild(leafNode);
319 if (null != dataNode) {
320 final Element element = doc.createElement(NOTIFICATION_ELEMENT_NAME);
321 final Element eventTime = doc.createElement(EVENT_TIME);
323 .setTextContent(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));
324 element.appendChild(element.getOwnerDocument().importNode(eventTime, true));
326 if (notificationType != null) {
327 final Element evtTypeElement = doc.createElementNS(nameSpace, notificationType);
328 evtTypeElement.appendChild(dataNode);
329 element.appendChild(element.getOwnerDocument().importNode(evtTypeElement, true));
331 element.appendChild(element.getOwnerDocument().importNode(dataNode, true));
334 result = convertDocumentToString(element);
336 } catch (ParserConfigurationException pce) {
337 LOG.error("Exception while converting the notification: {}", pce.getMessage());
343 private static String getNetConfReposneXMLForTC(List<ParameterDTO> parameters,
344 String notificationType, String nameSpace) {
345 String result = null;
347 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
348 docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
349 docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
350 DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
351 Document doc = docBuilder.newDocument();
352 final Element element = doc.createElement(NOTIFICATION_ELEMENT_NAME);
353 final Element eventTime = doc.createElement(EVENT_TIME);
354 eventTime.setTextContent(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));
355 element.appendChild(element.getOwnerDocument().importNode(eventTime, true));
357 final Element evtTypeElement = doc.createElementNS(nameSpace, notificationType);
359 for (ParameterDTO paramDto : parameters) {
360 final Element paramNode = doc.createElement(paramDto.getParamName());
361 paramNode.setTextContent(paramDto.getParamValue());
362 evtTypeElement.appendChild(paramNode);
364 element.appendChild(element.getOwnerDocument().importNode(evtTypeElement, true));
365 result = convertDocumentToString(element);
366 } catch (Exception e) {
367 LOG.error("Exception in getNetConfReposneXMLForTC: {}", e.getMessage());
372 public static String convertDocumentToString(Element element) {
373 String strxml = null;
375 TransformerFactory transformerFactory = TransformerFactory.newInstance();
376 transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
377 transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
378 Transformer transformer = transformerFactory.newTransformer();
379 DOMSource source = new DOMSource(element);
380 StreamResult result = new StreamResult(new StringWriter());
381 transformer.transform(source, result);
382 strxml = result.getWriter().toString();
383 } catch (Exception e) {
384 LOG.error("Error while converting Element to String", e);
386 LOG.debug("Converted XML is : {}", strxml);