--- /dev/null
+/*\r
+ * ============LICENSE_START========================================================================\r
+ * ONAP : tr-069-adapter\r
+ * =================================================================================================\r
+ * Copyright (C) 2020 CommScope Inc Intellectual Property.\r
+ * =================================================================================================\r
+ * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,\r
+ * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You\r
+ * may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
+ * either express or implied. See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ===============LICENSE_END=======================================================================\r
+ */\r
+\r
+package org.commscope.tr069adapter.netconf.notification;\r
+\r
+import java.io.IOException;\r
+import java.io.StringWriter;\r
+import java.text.SimpleDateFormat;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.StringTokenizer;\r
+\r
+import javax.xml.XMLConstants;\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+\r
+import org.commscope.tr069adapter.acs.common.DeviceInform;\r
+import org.commscope.tr069adapter.acs.common.ParameterDTO;\r
+import org.commscope.tr069adapter.netconf.rpc.CreateSubscription;\r
+import org.opendaylight.netconf.api.NetconfMessage;\r
+import org.opendaylight.netconf.api.xml.XmlNetconfConstants;\r
+import org.opendaylight.netconf.api.xml.XmlUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.springframework.stereotype.Component;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+import org.xml.sax.SAXException;\r
+\r
+@Component\r
+public class NetConfSessionUtil {\r
+\r
+ private static final Logger LOG = LoggerFactory.getLogger(NetConfSessionUtil.class);\r
+\r
+ private static final String INDEX_STR = "index";\r
+ private static final String INDEX_REGEX = "[0-9]{1,}";\r
+ private static final String NS_URI = "urn:onf:otcc:wireless:yang:tr069-notification";\r
+\r
+ public void sendNetConfNotification(DeviceInform notification) {\r
+ NetconfMessage netconfMessage = convertToNetConfMessage(notification);\r
+ LOG.debug("Notification converted to NetConf format {}", netconfMessage);\r
+ CreateSubscription.sendNotification(netconfMessage,\r
+ notification.getDeviceDetails().getDeviceId());\r
+ }\r
+\r
+ private NetconfMessage convertToNetConfMessage(DeviceInform notification) {\r
+ try {\r
+ String netConfXmlMsg = getNetconfResponseXML(notification);\r
+ if (netConfXmlMsg == null)\r
+ throw new IllegalArgumentException("There are no parameters found in the response");\r
+ return new NetconfMessage(XmlUtil.readXmlToDocument(netConfXmlMsg));\r
+ } catch (SAXException | IOException e) {\r
+ throw new IllegalArgumentException("Cannot parse notifications", e);\r
+ }\r
+ }\r
+\r
+ private static String getNetconfResponseXML(DeviceInform notification) {\r
+ if (notification == null || notification.getParameters().isEmpty()) {\r
+ LOG.debug("There are no parameters found in the response.");\r
+ return null;\r
+ }\r
+\r
+ List<ParameterDTO> parameters = notification.getParameters();\r
+\r
+ String result = null;\r
+ try {\r
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();\r
+ docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");\r
+ docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");\r
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();\r
+ Document doc = docBuilder.newDocument();\r
+\r
+ Map<String, Element> parentNodeMap = new HashMap<>();\r
+ Element dataNode = null; // root of all nodes\r
+\r
+ for (ParameterDTO paramDto : parameters) {\r
+ String paramName = paramDto.getParamName();\r
+ String paramValue = paramDto.getParamValue();\r
+ StringTokenizer tokenizer = new StringTokenizer(paramName, ".");\r
+ String parentNodeName = null;\r
+ StringBuilder parentNodeKey = null;\r
+ Element parentNode = null;\r
+ while (tokenizer.hasMoreElements()) {\r
+ String nodeName = (String) tokenizer.nextElement();\r
+ if (null == parentNodeName) { // construct first node or\r
+ // Device node\r
+ parentNodeName = nodeName;\r
+ parentNodeKey = new StringBuilder(nodeName);\r
+ // check if the node already exists in parentNodeMap\r
+ parentNode = parentNodeMap.get(parentNodeKey.toString());\r
+ if (null == dataNode) {\r
+ dataNode = parentNode;\r
+ }\r
+ } else if (nodeName.matches(INDEX_REGEX)) { // construct\r
+ // tabular and\r
+ // index nodes\r
+\r
+ // get parent tabular node from parent MAP\r
+ parentNodeKey = parentNodeKey.append(".").append(nodeName);\r
+ Element node = parentNodeMap.get(parentNodeKey.toString());\r
+\r
+ // create a tabular parent node if doesn't exit in MAP\r
+ if (null == node) {\r
+ node = doc.createElement(parentNodeName);\r
+ parentNodeMap.put(parentNodeKey.toString(), node);\r
+\r
+ // update current tabular parent node.\r
+ if (null != parentNode)\r
+ parentNode.appendChild(node);\r
+\r
+ // prepare and add index node to tabular parent node\r
+ Element indexNode = doc.createElement(INDEX_STR);\r
+ indexNode.setTextContent(nodeName);\r
+ node.appendChild(indexNode);\r
+ }\r
+ parentNode = node; // move parent to child\r
+ parentNodeName = nodeName;\r
+ } else if (parentNodeName.matches(INDEX_REGEX)) { // move to\r
+ // next\r
+ // node\r
+ // if\r
+ // tabular\r
+ // attribute\r
+ // is\r
+ // found\r
+ parentNodeKey = parentNodeKey.append(".").append(nodeName);\r
+ parentNodeName = nodeName;\r
+ } else {\r
+ // construct intermediate nodes\r
+ Element node = parentNodeMap.get(parentNodeKey.toString());\r
+ if (null == node) {\r
+ if (null == dataNode) {\r
+ node = doc.createElementNS(NS_URI, parentNodeName);\r
+ dataNode = node;\r
+ } else {\r
+ node = doc.createElement(parentNodeName);\r
+ }\r
+ parentNodeMap.put(parentNodeKey.toString(), node);\r
+ if (null != parentNode)\r
+ parentNode.appendChild(node);\r
+ }\r
+ parentNodeKey = parentNodeKey.append(".").append(nodeName);\r
+ parentNodeName = nodeName;\r
+ parentNode = node;\r
+ }\r
+ }\r
+ // construct leaf node\r
+ Element leafNode = doc.createElement(parentNodeName);\r
+ leafNode.setTextContent(paramValue);\r
+ if (null != parentNode)\r
+ parentNode.appendChild(leafNode);\r
+ }\r
+\r
+ if (null != dataNode) {\r
+ final Element element = doc.createElement(XmlNetconfConstants.NOTIFICATION_ELEMENT_NAME);\r
+ final Element eventTime = doc.createElement(XmlNetconfConstants.EVENT_TIME);\r
+ eventTime\r
+ .setTextContent(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));\r
+\r
+ final Element evtTypeElement =\r
+ doc.createElementNS(NS_URI, notification.getInformTypeList().get(0).toString());\r
+ evtTypeElement.appendChild(dataNode);\r
+ element.appendChild(element.getOwnerDocument().importNode(eventTime, true));\r
+ element.appendChild(element.getOwnerDocument().importNode(evtTypeElement, true));\r
+ result = convertDocumentToString(element);\r
+ }\r
+ } catch (ParserConfigurationException pce) {\r
+ LOG.error("Error while getNetconfResponseXML {}", pce.toString());\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ public static String convertDocumentToString(Element element) {\r
+ String strxml = null;\r
+ try {\r
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();\r
+ transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");\r
+ transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");\r
+ Transformer transformer = transformerFactory.newTransformer();\r
+ DOMSource source = new DOMSource(element);\r
+ StreamResult result = new StreamResult(new StringWriter());\r
+ transformer.transform(source, result);\r
+ strxml = result.getWriter().toString();\r
+ } catch (Exception e) {\r
+ LOG.error("Error while converting Element to String {}", e.toString());\r
+ }\r
+ LOG.debug("Converted XML is : {}", strxml);\r
+ return strxml;\r
+ }\r
+\r
+}\r