Development of NETCONF RPCs for tr-069 adapter to
[oam/tr069-adapter.git] / mapper / src / main / java / org / commscope / tr069adapter / mapper / util / NetconfToTr069MapperUtil.java
1 /*
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
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
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=======================================================================
17  */
18
19 package org.commscope.tr069adapter.mapper.util;
20
21 import java.io.Serializable;
22 import java.io.StringReader;
23 import java.io.StringWriter;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.StringTokenizer;
31
32 import javax.xml.XMLConstants;
33 import javax.xml.parsers.DocumentBuilder;
34 import javax.xml.parsers.DocumentBuilderFactory;
35 import javax.xml.parsers.ParserConfigurationException;
36 import javax.xml.transform.Transformer;
37 import javax.xml.transform.TransformerFactory;
38 import javax.xml.transform.dom.DOMSource;
39 import javax.xml.transform.stream.StreamResult;
40
41 import org.commscope.tr069adapter.acs.common.DeviceRPCRequest;
42 import org.commscope.tr069adapter.acs.common.DeviceRPCResponse;
43 import org.commscope.tr069adapter.acs.common.OperationOptions;
44 import org.commscope.tr069adapter.acs.common.ParameterDTO;
45 import org.commscope.tr069adapter.acs.common.dto.ParameterAttributeDTO;
46 import org.commscope.tr069adapter.acs.common.dto.TR069DeviceDetails;
47 import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode;
48 import org.commscope.tr069adapter.acs.common.dto.TR069OperationDetails;
49 import org.commscope.tr069adapter.mapper.MapperConfigProperties;
50 import org.commscope.tr069adapter.mapper.model.ErrorCodeDetails;
51 import org.commscope.tr069adapter.mapper.model.NetConfResponse;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.beans.factory.annotation.Autowired;
55 import org.springframework.stereotype.Component;
56 import org.w3c.dom.DOMImplementation;
57 import org.w3c.dom.Document;
58 import org.w3c.dom.DocumentType;
59 import org.w3c.dom.Element;
60 import org.w3c.dom.Node;
61 import org.w3c.dom.NodeList;
62 import org.xml.sax.InputSource;
63
64 @Component
65 public class NetconfToTr069MapperUtil {
66
67   @Autowired
68   MOMetaDataUtil metaDataUtil;
69
70   @Autowired
71   MapperConfigProperties config;
72
73   private static final Logger logger = LoggerFactory.getLogger(NetconfToTr069MapperUtil.class);
74   private static final String INDEX_STR = "index";
75   private static final String INDEX_REGEX = "[0-9]{1,}";
76   private static final String APPLICATION = "application";
77   private static final String OPERATION_FAILED = "operation-failed";
78   private static final String ERROR = "ERROR";
79   private static final String OPERATION_ABORTED = "Operation Aborted";
80   private static final String INDEX_NODE_FOUND = "Index node found : {}";
81
82   @Autowired
83   private ErrorCodeUtil errorCodeUtil;
84
85   public static Element convertStringToDocument(String xmlStr) {
86     try {
87       Document doc = convertStringToDocumentXml(xmlStr);
88       if (null != doc)
89         return doc.getDocumentElement();
90     } catch (Exception e) {
91       logger.error("Error while converting String to element {}", e.getMessage());
92     }
93     return null;
94   }
95
96   public static Document convertStringToDocumentXml(String xmlStr) {
97     try {
98       DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
99       factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
100       factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
101       DocumentBuilder builder;
102       builder = factory.newDocumentBuilder();
103       return builder.parse(new InputSource(new StringReader(xmlStr)));
104     } catch (Exception e) {
105       logger.error("Error while converting String to element {}", e.getMessage());
106     }
107     return null;
108   }
109
110   public static Map<String, String> extractRequestParamters(Document operationElement,
111       String netconfTag, String filterElement) {
112     Node requestDataNode = getParameterDataNode(operationElement, netconfTag, filterElement);
113     Map<String, String> result = new HashMap<>();
114     try {
115       result = getParameterMapForNode(requestDataNode, -1);
116     } catch (Exception e) {
117       logger.error("Error while getting parameter Map {}", e.getMessage());
118     }
119     return result;
120   }
121
122   public static DeviceRPCRequest prepareTR069Request(String deviceId, Element operationElement,
123       String netconfTag, TR069OperationCode opCode) {
124     Node requestDataNode = getDeviceDataNode(operationElement, netconfTag);
125     if (requestDataNode == null) {
126       logger.debug("No matching device parameters found in the netconf request XML.");
127       return null;
128     }
129     Map<String, String> map = getParameterMapForNode(requestDataNode, -1);
130     List<ParameterDTO> params = new ArrayList<>();
131
132     for (java.util.Map.Entry<String, String> entry : map.entrySet()) {
133       if (!entry.getKey().equalsIgnoreCase("filter")) {
134         String moName = entry.getKey();
135         String value = entry.getValue();
136         if (moName.endsWith("." + INDEX_STR)
137             && (TR069OperationCode.GET_PARAMETER_VALUES.equals(opCode)
138                 || TR069OperationCode.DELETE_OBJECT.equals(opCode))) {
139           logger.debug(INDEX_NODE_FOUND, moName);
140           moName = moName.replaceFirst("." + INDEX_STR, ".");
141           value = null;
142
143         }
144
145         ParameterDTO param = new ParameterDTO(moName, value);
146         params.add(param);
147       }
148     }
149
150     TR069OperationDetails opDetails = new TR069OperationDetails();
151     opDetails.setOpCode(opCode);
152     return handleParamsOperation(params, opDetails, deviceId);
153   }
154
155   public static DeviceRPCRequest handleParamsOperation(List<ParameterDTO> params,
156       TR069OperationDetails opDetails, String deviceId) {
157     opDetails.setParmeters(params);
158
159     DeviceRPCRequest deviceRPCRequest = new DeviceRPCRequest();
160     TR069DeviceDetails tr069DeviceDetails = new TR069DeviceDetails();
161     tr069DeviceDetails.setDeviceId(deviceId);
162     deviceRPCRequest.setOpDetails(opDetails);
163     deviceRPCRequest.setDeviceDetails(tr069DeviceDetails);
164     OperationOptions options = new OperationOptions();
165     options.setExecutionTimeout(60l);
166     deviceRPCRequest.setOptions(options);
167     return deviceRPCRequest;
168   }
169
170   public NetConfResponse getNetconfResponse(DeviceRPCResponse opResult, String swVersion,
171       String hwVersion, boolean isCustomparameter) {
172     NetConfResponse netConfResponse = new NetConfResponse();
173     ErrorCodeDetails errorCodeDetails = errorCodeUtil.getErrorCodeMetaData(opResult.getFaultKey());
174     ErrorCodeDetails errorCode = new ErrorCodeDetails();
175     if (errorCodeDetails != null) {
176       errorCode.setFaultCode(opResult.getFaultKey());
177       errorCode.setErrorMessage(errorCodeDetails.getErrorMessage());
178       errorCode.setErrorType(errorCodeDetails.getErrorType());
179       errorCode.setErrorTag(errorCodeDetails.getErrorTag());
180       errorCode.setErrorSeverity(errorCodeDetails.getErrorSeverity());
181       netConfResponse.setErrorCode(errorCode);
182       netConfResponse.setErrorMessage(opResult.getFaultString());
183     } else if (opResult.getFaultKey() != null && opResult.getFaultString() != null) {
184       errorCode.setFaultCode(opResult.getFaultKey());
185       errorCode.setErrorMessage(opResult.getFaultString());
186       errorCode.setErrorType(APPLICATION);
187       errorCode.setErrorTag(OPERATION_FAILED);
188       errorCode.setErrorSeverity(ERROR);
189       netConfResponse.setErrorCode(errorCode);
190       netConfResponse.setErrorMessage(opResult.getFaultString());
191     }
192     netConfResponse.setNetconfResponseXml(
193         getNetconfResponseXML(opResult.getOperationResponse().getParameterDTOs(), swVersion,
194             hwVersion, isCustomparameter));
195     return netConfResponse;
196   }
197
198   public NetConfResponse getNetconfResponseForSoftwareInventory(DeviceRPCResponse opResult,
199       String swVersion, String hwVersion) {
200
201     NetConfResponse netConfResponse = new NetConfResponse();
202     ErrorCodeDetails errorCodeDetails = errorCodeUtil.getErrorCodeMetaData(opResult.getFaultKey());
203     ErrorCodeDetails errorCode = new ErrorCodeDetails();
204     if (errorCodeDetails != null) {
205       errorCode.setFaultCode(opResult.getFaultKey());
206       errorCode.setErrorMessage(errorCodeDetails.getErrorMessage());
207       errorCode.setErrorType(errorCodeDetails.getErrorType());
208       errorCode.setErrorTag(errorCodeDetails.getErrorTag());
209       errorCode.setErrorSeverity(errorCodeDetails.getErrorSeverity());
210       netConfResponse.setErrorCode(errorCode);
211       netConfResponse.setErrorMessage(opResult.getFaultString());
212       return netConfResponse;
213     } else if (opResult.getFaultKey() != null && opResult.getFaultString() != null) {
214       errorCode.setFaultCode(opResult.getFaultKey());
215       errorCode.setErrorMessage(opResult.getFaultString());
216       errorCode.setErrorType(APPLICATION);
217       errorCode.setErrorTag(OPERATION_FAILED);
218       errorCode.setErrorSeverity(ERROR);
219       netConfResponse.setErrorCode(errorCode);
220       netConfResponse.setErrorMessage(opResult.getFaultString());
221       return netConfResponse;
222     }
223     List<ParameterDTO> paramDTOList = new ArrayList<>();
224
225     String build = null;
226     String productClass = null;
227     for (ParameterDTO paramDto : opResult.getOperationResponse().getParameterDTOs()) {
228       if (paramDto.getParamName().equals("Device.DeviceInfo.SoftwareVersion"))
229         build = paramDto.getParamValue();
230       else if (paramDto.getParamName().equals("Device.DeviceInfo.ProductClass"))
231         productClass = paramDto.getParamValue();
232     }
233
234     String[] arrOfBuild = build.split("\\.");
235     String buildId = arrOfBuild[arrOfBuild.length - 1];
236     StringBuilder buildVersion = new StringBuilder();
237     for (int i = 0; i < arrOfBuild.length - 1; i++) {
238       if (i == arrOfBuild.length - 2) {
239         buildVersion.append(arrOfBuild[i]);
240       } else {
241         buildVersion.append(arrOfBuild[i]);
242         buildVersion.append(".");
243       }
244     }
245
246     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.name", "Active Partition"));
247     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.status", "VALID"));
248     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.active", "true"));
249     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.running", "true"));
250     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.access", "READ_ONLY"));
251     paramDTOList
252         .add(new ParameterDTO("software-inventory.software-slot.product-code", productClass));
253     paramDTOList.add(
254         new ParameterDTO("software-inventory.software-slot.vendor-code", config.getVendorName()));
255     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.build-id", buildId));
256     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.build-version",
257         buildVersion.toString()));
258     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.files.name", "BC_ONE"));
259     paramDTOList.add(new ParameterDTO("software-inventory.software-slot.files.integrity", "OK"));
260
261     String xmlStr = getNetconfResponseXML(paramDTOList, swVersion, hwVersion, true);
262
263     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
264     factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
265     factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
266     DocumentBuilder builder;
267     Document doc = null;
268     try {
269       builder = factory.newDocumentBuilder();
270       doc = builder.parse(new InputSource(new StringReader(xmlStr)));
271     } catch (Exception e) {
272       logger.error("Error while converting String to element", e);
273       errorCode.setFaultCode("8002");
274       errorCode.setErrorMessage(OPERATION_ABORTED);
275       errorCode.setErrorType(APPLICATION);
276       errorCode.setErrorTag(OPERATION_FAILED);
277       errorCode.setErrorSeverity(ERROR);
278       netConfResponse.setErrorCode(errorCode);
279       netConfResponse.setErrorMessage(OPERATION_ABORTED);
280       return netConfResponse;
281     }
282
283     Element originalDocumentElement = doc.getDocumentElement();
284     Element newDocumentElement = doc.createElementNS("urn:o-ran:software-management:1.0",
285         originalDocumentElement.getNodeName());
286     NodeList list = originalDocumentElement.getChildNodes();
287     while (list.getLength() != 0) {
288       newDocumentElement.appendChild(list.item(0));
289     }
290     // Replace the original element
291     doc.replaceChild(newDocumentElement, originalDocumentElement);
292
293     String strxml = null;
294     try {
295       TransformerFactory transformerFactory = TransformerFactory.newInstance();
296       transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
297       transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
298       Transformer transformer = transformerFactory.newTransformer();
299       DOMSource source = new DOMSource(doc);
300       StreamResult result = new StreamResult(new StringWriter());
301       transformer.transform(source, result);
302       strxml = result.getWriter().toString();
303     } catch (Exception e) {
304       logger.error("Error while converting Element to String", e);
305       errorCode.setFaultCode("8002");
306       errorCode.setErrorMessage(OPERATION_ABORTED);
307       errorCode.setErrorType(APPLICATION);
308       errorCode.setErrorTag(OPERATION_FAILED);
309       errorCode.setErrorSeverity(ERROR);
310       netConfResponse.setErrorCode(errorCode);
311       netConfResponse.setErrorMessage(OPERATION_ABORTED);
312       return netConfResponse;
313     }
314
315     netConfResponse.setNetconfResponseXml(strxml);
316     logger.debug("NetConf Response XML String for software inventory:{} ", strxml);
317     return netConfResponse;
318   }
319
320   public NetConfResponse getNetconfResponseForRequestWithoutInputParams(
321       DeviceRPCResponse opResult) {
322     NetConfResponse netConfResponse = new NetConfResponse();
323     ErrorCodeDetails errorCodeDetails = errorCodeUtil.getErrorCodeMetaData(opResult.getFaultKey());
324     ErrorCodeDetails errorCode = new ErrorCodeDetails();
325     if (errorCodeDetails != null) {
326       errorCode.setFaultCode(opResult.getFaultKey());
327       errorCode.setErrorMessage(errorCodeDetails.getErrorMessage());
328       errorCode.setErrorType(errorCodeDetails.getErrorType());
329       errorCode.setErrorTag(errorCodeDetails.getErrorTag());
330       errorCode.setErrorSeverity(errorCodeDetails.getErrorSeverity());
331       netConfResponse.setErrorCode(errorCode);
332       netConfResponse.setErrorMessage(opResult.getFaultString());
333     } else if (opResult.getFaultKey() != null && opResult.getFaultString() != null) {
334       errorCode.setFaultCode(opResult.getFaultKey());
335       errorCode.setErrorMessage(opResult.getFaultString());
336       errorCode.setErrorType(APPLICATION);
337       errorCode.setErrorTag(OPERATION_FAILED);
338       errorCode.setErrorSeverity(ERROR);
339       netConfResponse.setErrorCode(errorCode);
340       netConfResponse.setErrorMessage(opResult.getFaultString());
341     }
342     String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rpc-reply><OK>true</OK></rpc-reply>";
343     netConfResponse.setNetconfResponseXml(xml);
344     return netConfResponse;
345   }
346
347   public NetConfResponse getNetconfResponseForGPA(DeviceRPCResponse opResult, String swVersion,
348       String hwVersion) {
349     NetConfResponse netConfResponse = new NetConfResponse();
350     ErrorCodeDetails errorCodeDetails = errorCodeUtil.getErrorCodeMetaData(opResult.getFaultKey());
351     ErrorCodeDetails errorCode = new ErrorCodeDetails();
352     if (errorCodeDetails != null) {
353       errorCode.setFaultCode(opResult.getFaultKey());
354       errorCode.setErrorMessage(errorCodeDetails.getErrorMessage());
355       errorCode.setErrorType(errorCodeDetails.getErrorType());
356       errorCode.setErrorTag(errorCodeDetails.getErrorTag());
357       errorCode.setErrorSeverity(errorCodeDetails.getErrorSeverity());
358       netConfResponse.setErrorCode(errorCode);
359       netConfResponse.setErrorMessage(opResult.getFaultString());
360     } else if (opResult.getFaultKey() != null && opResult.getFaultString() != null) {
361       errorCode.setFaultCode(opResult.getFaultKey());
362       errorCode.setErrorMessage(opResult.getFaultString());
363       errorCode.setErrorType(APPLICATION);
364       errorCode.setErrorTag(OPERATION_FAILED);
365       errorCode.setErrorSeverity(ERROR);
366       netConfResponse.setErrorCode(errorCode);
367       netConfResponse.setErrorMessage(opResult.getFaultString());
368     }
369     netConfResponse.setNetconfResponseXml(getGPANetconfResponseXML(
370         opResult.getOperationResponse().getParameterDTOs(), swVersion, hwVersion));
371     return netConfResponse;
372   }
373
374   private String getGPANetconfResponseXML(List<ParameterDTO> parameters, String swVersion,
375       String hwVersion) {
376
377     try {
378       DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
379       docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
380       docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
381       DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
382       DOMImplementation impl = docBuilder.getDOMImplementation();
383       Document doc = impl.createDocument(null, "rpc-reply", (DocumentType) null);
384       Element parent = doc.getDocumentElement();
385       Element child = null;
386       String result = null;
387       int i = 1;
388       for (ParameterDTO param : parameters) {
389         child = doc.createElement("ns1:data");
390         Element keyNode = doc.createElement("ns1:keyindex");
391         keyNode.setTextContent(String.valueOf(i));
392         child.appendChild(keyNode);
393         i++;
394         List<ParameterDTO> paramList = new ArrayList<>();
395         paramList.add(param);
396         String paramName = metaDataUtil
397             .getNetconfXPathNameByTR69NameWithIndexes(param.getParamName(), swVersion, hwVersion);
398         Element parameterTag = doc.createElement("ns1:parameter");
399         parameterTag.setTextContent(paramName);
400         child.appendChild(parameterTag);
401         String[] accesslist = ((ParameterAttributeDTO) param).getAccessList();
402         int notification = ((ParameterAttributeDTO) param).getNotification();
403         Element notfChild = doc.createElement("ns1:notification");
404         notfChild.setTextContent(String.valueOf(notification));
405         child.appendChild(notfChild);
406         for (String access : accesslist) {
407           Element accChild = doc.createElement("ns1:access-list");
408           accChild.setTextContent(access);
409           child.appendChild(accChild);
410         }
411
412         parent.appendChild(child);
413       }
414       result = convertDocumentToString(parent);
415       return result;
416     } catch (Exception e) {
417       logger.error("Exception in getGPANetconfResponseXML: {}", e.getMessage());
418     }
419     return null;
420   }
421
422   public String getNetconfResponseXML(List<ParameterDTO> parameters, String swVersion,
423       String hwVersion, boolean isCustomparameter) {
424     if (null == parameters || parameters.isEmpty()) {
425       logger.debug("There are no parameters found in the response.");
426       return null;
427     }
428     Collections.sort(parameters, new SortByParamterName());
429
430     String result = null;
431     try {
432       Document doc = null;
433       Element dataNode = getNetconfResponseXMLElement(parameters, isCustomparameter, doc, false,
434           swVersion, hwVersion);
435       if (null != dataNode) {
436         result = convertDocumentToString(dataNode);
437       }
438     } catch (Exception pce) {
439       logger.error("Exception: {}", pce.getMessage());
440     }
441
442     return result;
443   }
444
445   private Element getNetconfResponseXMLElement(List<ParameterDTO> parameters,
446       boolean isCustomparameter, Document doc, boolean isGPA, String swVersion, String hwVersion) {
447     if (null == parameters || parameters.isEmpty()) {
448       return null;
449     }
450     Collections.sort(parameters, new SortByParamterName());
451     try {
452       if (doc == null) {
453         DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
454         docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
455         docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
456         DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
457         doc = docBuilder.newDocument();
458       }
459
460       Map<String, Element> parentNodeMap = new HashMap<>();
461       Element dataNode = null; // root of all nodes
462
463       for (ParameterDTO paramDto : parameters) {
464         String paramName = metaDataUtil.getNetconfNameByTR69NameWithIndexes(paramDto.getParamName(),
465             swVersion, hwVersion);
466         if (paramName == null && isCustomparameter) {
467           paramName = paramDto.getParamName();
468         }
469         String paramValue = paramDto.getParamValue();
470
471         if ((!isGPA) && (paramValue == null || paramValue.trim().isEmpty())) {
472           logger.debug("Values is empty so skipping this parameter.");
473           continue;
474         }
475         StringTokenizer tokenizer = new StringTokenizer(paramName, ".");
476         String parentNodeName = null;
477         String parentNodeKey = null;
478         Element parentNode = null;
479         while (tokenizer.hasMoreElements()) {
480           String nodeName = (String) tokenizer.nextElement();
481           if (null == parentNodeName) { // construct first node or
482                                         // Device node
483             parentNodeName = nodeName;
484             parentNodeKey = nodeName;
485             // check if the node already exists in parentNodeMap
486             parentNode = parentNodeMap.get(parentNodeKey);
487             if (null == dataNode) {
488               dataNode = parentNode;
489             }
490             continue;
491           } else if (nodeName.matches(INDEX_REGEX)) { // construct
492                                                       // tabular and
493                                                       // index nodes
494
495             // get parent tabular node from parent MAP
496             StringBuilder bld = new StringBuilder();
497             bld.append(parentNodeKey);
498             bld.append(".");
499             bld.append(nodeName);
500             parentNodeKey = bld.toString();
501             Element node = parentNodeMap.get(parentNodeKey);
502
503             // create a tabular parent node if doesn't exit in MAP
504             if (null == node) {
505               if ((!isGPA)
506                   && metaDataUtil.getMetaDataByNetConfName(parentNodeKey + ".", swVersion,
507                       hwVersion) != null
508                   && metaDataUtil
509                       .getMetaDataByNetConfName(parentNodeKey + ".", swVersion, hwVersion)
510                       .getURI() != null) {
511                 node = doc.createElementNS(metaDataUtil
512                     .getMetaDataByNetConfName(parentNodeKey + ".", swVersion, hwVersion).getURI(),
513                     parentNodeName);
514               } else {
515                 node = doc.createElement(parentNodeName);
516               }
517               parentNodeMap.put(parentNodeKey, node);
518
519               // update current tabular parent node.
520               if (null != parentNode)
521                 parentNode.appendChild(node);
522
523               // prepare and add index node to tabular parent node
524               Element indexNode = doc.createElement(INDEX_STR);
525               indexNode.setTextContent(nodeName);
526               node.appendChild(indexNode);
527             }
528             parentNode = node; // move parent to child
529             parentNodeName = nodeName;
530           } else if (parentNodeName.matches(INDEX_REGEX)) { // move to
531                                                             // next
532                                                             // node
533                                                             // if
534                                                             // tabular
535                                                             // attribute
536                                                             // is
537                                                             // found
538             StringBuilder bld = new StringBuilder();
539             bld.append(parentNodeKey);
540             bld.append(".");
541             bld.append(nodeName);
542             parentNodeKey = bld.toString();
543             parentNodeName = nodeName;
544           } else {
545             // construct intermediate nodes
546             Element node = parentNodeMap.get(parentNodeKey);
547             if (null == node) {
548               if ((!isGPA)
549                   && metaDataUtil.getMetaDataByNetConfName(parentNodeKey, swVersion,
550                       hwVersion) != null
551                   && metaDataUtil.getMetaDataByNetConfName(parentNodeKey, swVersion, hwVersion)
552                       .getURI() != null) {
553                 node = doc.createElementNS(metaDataUtil
554                     .getMetaDataByNetConfName(parentNodeKey, swVersion, hwVersion).getURI(),
555                     parentNodeName);
556
557               } else {
558                 node = doc.createElement(parentNodeName);
559               }
560               if (dataNode == null)
561                 dataNode = node;
562               parentNodeMap.put(parentNodeKey, node);
563               if (null != parentNode)
564                 parentNode.appendChild(node);
565
566             }
567             StringBuilder bld = new StringBuilder();
568             bld.append(parentNodeKey);
569             bld.append(".");
570             bld.append(nodeName);
571             parentNodeKey = bld.toString();
572             parentNodeName = nodeName;
573             parentNode = node;
574           }
575         }
576         // construct leaf node
577         Element leafNode = doc.createElement(parentNodeName);
578         leafNode.setTextContent(paramValue);
579         if (parentNode != null)
580           parentNode.appendChild(leafNode);
581       }
582
583       if (null != dataNode) {
584         return dataNode;
585       }
586     } catch (ParserConfigurationException pce) {
587       logger.error("Response xml formatting is failed : {} ", pce.toString());
588     }
589
590     return null;
591   }
592
593   public ParameterDTO getParamNameAndValueForGPA(Element operationElement, String netconfTag,
594       String swVersion, String hwVersion) {
595     Node deviceNode = getDeviceDataNode(operationElement, netconfTag);
596     Map<String, String> map = null;
597     try {
598       map = getParameterMapForNode(deviceNode, -1);
599     } catch (Exception e) {
600       logger.error("Exception in getParamNameAndValueForGPA: {}", e.getMessage());
601       return null;
602     }
603     ParameterDTO param = new ParameterDTO();
604     for (String moName : map.keySet()) {
605       if (moName.endsWith("." + INDEX_STR)) {
606         logger.debug(INDEX_NODE_FOUND, moName);
607         moName = moName.replaceFirst("." + INDEX_STR, ".");
608       }
609       String tr069Moname =
610           metaDataUtil.getTR069NameByNetconfNameWithIndexes(moName, swVersion, hwVersion);
611       param.setParamName(tr069Moname);
612       param.setParamValue("");
613     }
614     return param;
615   }
616
617   public ParameterAttributeDTO getParamNameAndValueForSPA(Element operationElement,
618       String netconfTag, String swVersion, String hwVersion) {
619     Node requestDataNode = getDeviceDataNode(operationElement, netconfTag);
620     if (requestDataNode == null) {
621       logger.debug("No matching device parameters found in the netconf request XML.");
622     }
623     Node deviceNode = getDeviceDataNode(operationElement, "parameter");
624     Map<String, String> map = new HashMap<>();
625     try {
626       map = getParameterMapForNode(deviceNode, -1);
627     } catch (Exception e) {
628       logger.error("Error while getting parameter Map {}", e.getMessage());
629     }
630
631     NodeList nodeList = operationElement.getChildNodes();
632     int length = nodeList.getLength();
633     String notificationVal = null;
634     List<String> accessList = new ArrayList<>();
635     String accesslistChange = null;
636     String notificationChange = null;
637     for (int i = 0; i < length; i++) {
638       if (nodeList.item(i).getNodeName().equals("notification")) {
639         notificationVal = nodeList.item(i).getTextContent();
640       } else if (nodeList.item(i).getNodeName().equals("access-list")) {
641         if (nodeList.item(i).getTextContent() != null
642             && !(nodeList.item(i).getTextContent().isEmpty())) {
643           accessList.add(nodeList.item(i).getTextContent());
644         }
645       } else if (nodeList.item(i).getNodeName().equals("access-list-change")) {
646         accesslistChange = nodeList.item(i).getTextContent();
647       } else if (nodeList.item(i).getNodeName().equals("notification-change")) {
648         notificationChange = nodeList.item(i).getTextContent();
649       }
650     }
651     String[] accList = accessList.toArray(new String[accessList.size()]);
652     ParameterAttributeDTO param = new ParameterAttributeDTO();
653     param.setAccessList(accList);
654     param.setNotification(Integer.valueOf(notificationVal));
655     param.setAccesslistChange(Boolean.parseBoolean(accesslistChange));
656     param.setNotificationChange(Boolean.parseBoolean(notificationChange));
657
658     for (String moName : map.keySet()) {
659       if (moName.endsWith("." + INDEX_STR)) {
660         logger.debug(INDEX_NODE_FOUND, moName);
661         moName = moName.replaceFirst("." + INDEX_STR, ".");
662       }
663       String tr069Moname =
664           metaDataUtil.getTR069NameByNetconfNameWithIndexes(moName, swVersion, hwVersion);
665       param.setParamName(tr069Moname);
666       param.setParamValue("");
667     }
668
669     return param;
670   }
671
672   public static String convertDocumentToString(Element element) {
673     String strxml = null;
674     try {
675       TransformerFactory transformerFactory = TransformerFactory.newInstance();
676       transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
677       transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
678       Transformer transformer = transformerFactory.newTransformer();
679       DOMSource source = new DOMSource(element);
680       StreamResult result = new StreamResult(new StringWriter());
681       transformer.transform(source, result);
682       strxml = result.getWriter().toString();
683     } catch (Exception e) {
684       logger.error("Error while converting Element to String {}", e.toString());
685     }
686     logger.debug("Converted XML is : {} ", strxml);
687     return strxml;
688   }
689
690   // TODO: Need to optimize the Node element logic for better performance
691   private static Map<String, String> getParameterMapForNode(Node moRNode, int numberOfChilds) {
692     Map<String, String> result = new HashMap<>();
693     if (moRNode.getNodeType() == Node.ELEMENT_NODE) {
694       NodeList childs = moRNode.getChildNodes();
695       boolean hasChildElements = false;
696       hasChildElements = checkMoreElements(result, childs, hasChildElements);
697       if (!hasChildElements) {
698         String moName = getMOName(moRNode);
699         if (moName.contains("software-inventory")) {
700           result.put("device.device-info.software-version", moRNode.getTextContent());
701           result.put("device.device-info.product-class", moRNode.getTextContent());
702         } else if (!moName.endsWith("." + INDEX_STR)) {
703           result.put(moName, moRNode.getTextContent());
704         } else if (numberOfChilds == 1) {
705           result.put(moName, moRNode.getTextContent());
706         }
707       }
708     }
709
710     return result;
711   }
712
713   private static boolean checkMoreElements(Map<String, String> result, NodeList childs,
714       boolean hasChildElements) {
715     if (childs.getLength() > 0) {
716       int counter = 0;
717       for (int i = 0; i < childs.getLength(); i++) {
718         Node cNode = childs.item(i);
719         if (cNode != null && cNode.getNodeType() == Node.ELEMENT_NODE) {
720           counter++;
721         }
722       }
723
724       for (int i = 0; i < childs.getLength(); i++) {
725         Node cNode = childs.item(i);
726         if (cNode != null && cNode.getNodeType() == Node.ELEMENT_NODE) {
727           hasChildElements = true;
728           Map<String, String> subResult = getParameterMapForNode(cNode, counter);
729           result.putAll(subResult);
730         }
731       }
732     }
733     return hasChildElements;
734   }
735
736   private static String getMOName(Node moRNode) {
737     String result = removeNS(moRNode.getNodeName());
738     Node pNode = moRNode;
739     while (true) {
740       pNode = pNode.getParentNode();
741       if (pNode == null || pNode.getNodeType() != Node.ELEMENT_NODE
742           || pNode.getNodeName().equals("edit-config") || pNode.getNodeName().equals("config")
743           || pNode.getNodeName().equals("get-config") || pNode.getNodeName().equals("filter")
744           || pNode.getNodeName().equals("get") || pNode.getNodeName().equals("parameter")) {
745         return result;
746       } else {
747         String indexStr = getMOIndex(pNode);
748         StringBuilder bld = new StringBuilder(removeNS(pNode.getNodeName()));
749         bld.append(".");
750         if (indexStr == null) {
751           bld.append(result);
752           result = bld.toString();
753         } else {
754           bld.append(indexStr);
755           bld.append(".");
756           bld.append(result);
757           result = bld.toString();
758         }
759       }
760     }
761   }
762
763   private static Node getParameterDataNode(Document el, String docStart, String filterElement) {
764     NodeList nodeList = el.getElementsByTagName(docStart);
765     if (nodeList.getLength() > 0) {
766       nodeList = nodeList.item(0).getChildNodes();
767       for (int i = 0; i < nodeList.getLength(); i++) {
768         Node node = nodeList.item(i);
769         String nodeName = removeNS(node.getNodeName());
770         if (nodeName.equals(filterElement)) {
771           return node;
772         }
773       }
774     }
775     return null;
776   }
777
778   private static Node getDeviceDataNode(Element el, String filter) {
779     try {
780       NodeList nodeList = el.getElementsByTagName(filter);
781       if (nodeList.getLength() > 0) {
782         nodeList = nodeList.item(0).getChildNodes();
783         for (int i = 0; i < nodeList.getLength(); i++) {
784           Node node = nodeList.item(i);
785           if (node.getNodeType() == Node.ELEMENT_NODE) {
786             return node;
787           }
788         }
789       }
790     } catch (Exception e) {
791       logger.error("exception occured while parsing the request xml {}", e.getMessage());
792     }
793     return null;
794   }
795
796   private static String removeNS(String nodeName) {
797     // remove name space
798     int li = nodeName.lastIndexOf(':');
799     nodeName = nodeName.substring(li + 1);
800     return nodeName;
801   }
802
803   private static String getMOIndex(Node pNode) {
804     if (null != pNode) {
805       NodeList nodeList = pNode.getChildNodes();
806       for (int i = 0; i < nodeList.getLength(); i++) {
807         Node childNode = nodeList.item(i);
808         String nodeName = removeNS(childNode.getNodeName());
809         if (nodeName.equalsIgnoreCase(INDEX_STR)) {
810           return childNode.getTextContent();
811         }
812       }
813     }
814     return null;
815   }
816 }
817
818
819 class SortByParamterName implements Comparator<ParameterDTO>, Serializable {
820   private static final long serialVersionUID = 3010693349267067945L;
821
822   public int compare(ParameterDTO a, ParameterDTO b) {
823     return a.getParamName().compareTo(b.getParamName());
824   }
825 }