create custom spring aop annotation for logging
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / onap / so / bpmn / common / scripts / MsoUtils.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.bpmn.common.scripts
24
25 import org.onap.so.logger.LoggingAnchor
26 import org.onap.logging.filter.base.ErrorCode
27
28 import java.text.SimpleDateFormat
29
30 import org.apache.commons.codec.binary.Base64
31 import org.apache.commons.lang3.StringEscapeUtils
32 import org.onap.so.bpmn.core.xml.XmlTool
33 import org.onap.so.logger.MessageEnum
34 import org.slf4j.Logger
35 import org.slf4j.LoggerFactory
36 import org.onap.so.utils.CryptoUtils
37 import org.slf4j.MDC
38 import org.w3c.dom.Element
39
40 import groovy.util.slurpersupport.NodeChild
41 import groovy.xml.XmlUtil
42
43 class MsoUtils {
44     private static final Logger logger = LoggerFactory.getLogger( MsoUtils.class);
45
46         def initializeEndPoints(execution){
47                 // use this placeholder to initialize end points, if called independently, this need to be set
48                 execution.setVariable("AAIEndPoint","http://localhost:28080/SoapUIMocks")
49         }
50
51         /**
52          * Returns the unescaped contents of element
53          *
54          * @param xmlInput
55          * @param element
56          * @return
57          */
58         def getNodeText(xmlInput,element){
59                 def rtn=null
60                 if(xmlInput!=null){
61                         def xml= new XmlSlurper().parseText(xmlInput)
62                         rtn= xml.'**'.find{node->node.name()==element}
63                         if (rtn != null){
64                                 rtn=rtn.text()
65                         }
66                 }
67                 return rtn
68         }
69         def getMultNodes(xmlInput, element){
70                 def nodes=null
71                 if(xmlInput!=null){
72                         def xml= new XmlSlurper().parseText(xmlInput)
73                         nodes = xml.'**'.findAll{ node-> node.name() == element }*.text()
74                 }
75                 return nodes
76         }
77         /**
78          * Note: this uses XmlParser instead of XmlSlurper, thus it is not as
79          * efficient because it instantiates the whole DOM tree.
80          * @param xmlInput
81          * @param element
82          * @return a list of Nodes, or {@code null} if <i>xmlInput</i> is {@code null}
83          */
84         def getMultNodeObjects(xmlInput, element){
85                 def nodes=null
86                 if(xmlInput!=null){
87                         def xml= new XmlParser().parseText(xmlInput)
88                         nodes = xml.'**'.findAll{ node-> node.name() == element }
89                 }
90                 return nodes
91         }
92
93         def getNodeXml(xmlInput,element){
94                 return getNodeXml(xmlInput, element, true)
95         }
96         def getNodeXml(xmlInput,element,incPreamble){
97                 def fxml= new XmlSlurper().parseText(xmlInput)
98                 NodeChild nodeToSerialize = fxml.'**'.find {it.name() == element}
99                 if(nodeToSerialize==null){
100                         return ""
101                 }
102                 def nodeAsText = XmlUtil.serialize(nodeToSerialize)
103                 if (!incPreamble) {
104                         nodeAsText = removeXmlPreamble(nodeAsText)
105                 }
106
107                 return unescapeNodeContents(nodeToSerialize, nodeAsText)
108         }
109
110         def unescapeNodeContents(NodeChild node, String text) {
111                 if (!node.childNodes().hasNext()) {
112                         return StringEscapeUtils.unescapeXml(text)
113                 } else {
114                         return text
115                 }
116         }
117
118         def nodeExists(xmlInput,element){
119                 try {
120                         def fxml= new XmlSlurper().parseText(xmlInput)
121                         def nodeToSerialize = fxml.'**'.find {it.name() == element}
122                         return nodeToSerialize!=null
123                 } catch(Exception e) {
124                         return false
125                 }
126         }
127
128
129         /***** Utilities when using XmlParser *****/
130
131         /**
132          * Convert a Node into a String by deserializing it and formatting it.
133          *
134          * @param node Node to be converted.
135          * @return the Node as a String.
136          */
137         def String nodeToString(Node node) {
138                 def String nodeAsString = groovy.xml.XmlUtil.serialize(node)
139                 nodeAsString = removeXmlPreamble(nodeAsString)
140                 return formatXml(nodeAsString)
141         }
142
143         /**
144          * Get the specified child Node of the specified parent. If there are
145          * multiple children of the same name, only the first one is returned.
146          * If there are no children with the specified name, 'null' is returned.
147          *
148          * @param parent Parent Node in which to find a child.
149          * @param childNodeName Name of the child Node to get.
150          * @return the (first) child Node with the specified name or 'null'
151          * if a child Node with the specified name does not exist.
152          */
153         def Node getChildNode(Node parent, String childNodeName) {
154                 def NodeList nodeList = getIdenticalChildren(parent, childNodeName)
155                 if (nodeList.size() == 0) {
156                         return null
157                 } else {
158                         return nodeList.get(0)
159                 }
160         }
161
162         /**
163          * Get the textual value of the specified child Node of the specified parent.
164          * If there are no children with the specified name, 'null' is returned.
165          *
166          * @param parent Parent Node in which to find a child.
167          * @param childNodeName Name of the child Node whose value to get.
168          * @return the textual value of child Node with the specified name or 'null'
169          * if a child Node with the specified name does not exist.
170          */
171         def String getChildNodeText(Node parent, String childNodeName) {
172                 def Node childNode = getChildNode(parent, childNodeName)
173                 if (childNode == null) {
174                         return null
175                 } else {
176                         return childNode.text()
177                 }
178         }
179
180         /**
181          * Get all of the child nodes from the specified parent that have the
182          * specified name.  The returned NodeList could be empty.
183          *
184          * @param parent Parent Node in which to find children.
185          * @param childNodeName Name of the children to get.
186          * @return a NodeList of all the children from the parent with the specified
187          * name. The list could be empty.
188          */
189         def NodeList getIdenticalChildren(Node parent, String childNodeName) {
190                 return (NodeList) parent.get(childNodeName)
191         }
192
193         /***** End of Utilities when using XmlParser *****/
194
195
196         /** these are covered under the common function above**/
197         def getSubscriberName(xmlInput,element){
198                 def rtn=null
199                 if(xmlInput!=null){
200                         def xml= new XmlSlurper().parseText(xmlInput)
201                         rtn= xml.'**'.find{node->node.name()==element}.text()
202                 }
203                 return rtn
204         }
205         def getTenantInformation(xmlInput,element){
206                 def xml= new XmlSlurper().parseText(xmlInput)
207                 def nodeToSerialize = xml.'**'.find {it.name() == 'service-information'}
208                 def nodeAsText = XmlUtil.serialize(nodeToSerialize)
209                 return nodeAsText
210         }
211         def getServiceInstanceId(xmlInput,element){
212                 def xml= new XmlSlurper().parseText(xmlInput)
213                 return ( xml.'**'.find{node->node.name()==element}.text() )
214         }
215         //for aai tenant url
216         def searchResourceLink(xmlInput, resourceType){
217                 def fxml= new XmlSlurper().parseText(xmlInput)
218                 def element = fxml.'**'.find {it.'resource-type' == resourceType}
219                 return (element == null) ? null : element.'resource-link'.text()
220         }
221
222         def searchMetaData(xmlInput, searchName, searchValue){
223                 def fxml= new XmlSlurper().parseText(xmlInput)
224                 def ret = fxml.'**'.find {it.metaname.text() == searchName && it.metaval.text() == searchValue}
225                 if(ret != null){
226                         return ret.parent().parent()
227                 }
228                 return ret
229         }
230
231         def searchMetaDataNode(fxml, searchName, searchValue){
232                 def ret = fxml.'**'.find {it.metaname.text() == searchName && it.metaval.text() == searchValue}
233                 if(ret != null){
234                         return ret.parent().parent()
235                 }
236                 return ret
237         }
238
239         // for Trinity L3 add/delete bonding
240         def getPBGFList(isDebugLogEnabled, xmlInput){
241                 log("DEBUG", "getPBGFList: xmlInput " + xmlInput,isDebugLogEnabled)
242                 ArrayList myNodes = new ArrayList()
243                 if(nodeExists(xmlInput,"nbnc-response-information")){
244                 def respInfo=getNodeXml(xmlInput,"nbnc-response-information", false)
245                 if(respInfo!=null){
246                         def fxml= new XmlSlurper().parseText(respInfo)
247                         fxml.'virtual-datacenter-list'.each { vdc ->
248                                 //we only want to add two BGF per VDC, BGF1 and BGF2
249                                         def routerList = vdc.'router-list'.first()
250                                         routerList.each{ myList ->
251                                                 def physNodes  = myList.'**'.findAll {it.'border-element-tangibility'.text() =~ /PHYSICAL/}
252                                                 def nodeToAdd
253                                                 physNodes.each{
254                                                         if(nodeToAdd==null){
255                                                                 nodeToAdd = it
256                                                         }else{
257                                                                 def beid = nodeToAdd.'border-element-id'.text() +
258                                                                          " " + nodeToAdd.'border-element-type'.text() +
259                                                                          " and " +
260                                                                          it.'border-element-id'.text() +
261                                                                          " " + it.'border-element-type'.text()
262                                                                 def mytag = nodeToAdd.'border-element-id'
263                                                                 mytag[0].replaceBody(beid)
264                                                         }
265                                                 }
266                                                 def mytag = nodeToAdd.'vlan-id'
267                                                 def ind = mytag.text().indexOf('.')
268                                                 if(ind >= 0){
269                                                         def vlan = mytag.text().substring(0,ind)
270                                                         mytag[0].replaceBody(vlan)
271                                                 }
272                                                 myNodes.add(XmlUtil.serialize(nodeToAdd))
273                                         }
274                         }
275                 }
276                         return myNodes
277                 }else{
278                         return null
279                 }
280         }
281
282         def getPBGFList(xmlInput){
283                 getPBGFList("false", xmlInput)
284         }
285
286         def getMetaVal(node, name){
287                 try{
288                         return node.'**'.find {it.metaname.text() == name}.metaval.text()
289                 }catch(Exception e){
290                         return null
291                 }
292         }
293
294         def private log(logmode,logtxt,isDebugLogEnabled="false"){
295                 if ("INFO"==logmode) {
296                         logger.info(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), logtxt, "BPMN");
297                 } else if ("WARN"==logmode) {
298                         logger.warn (LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_WARNING.toString(), logtxt, "BPMN",
299                                         ErrorCode.UnknownError.getValue(), logtxt);
300                 } else if ("ERROR"==logmode) {
301                     logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), logtxt, "BPMN",
302                                         ErrorCode.UnknownError.getValue(), logtxt);
303                 } else {
304                         logger.debug(logtxt);
305                 }
306         }
307
308         // headers: header - name-value
309         def getHeaderNameValue(xmlInput, nameAttribute){
310                 def rtn=null
311                 if(xmlInput!=null){
312                         def xml= new XmlSlurper().parseText(xmlInput)
313                         rtn= xml.'**'.find {header->header.'@name'.text() == nameAttribute}.'@value'
314                 }
315                 return rtn
316         }
317
318         /**
319          * Gets the children of the specified element.
320          */
321         public String getChildNodes(xmlInput, element) {
322                 def xml= new XmlSlurper().parseText(xmlInput)
323                 def thisElement = xml.'**'.find {it.name() == element}
324                 StringBuilder out = new StringBuilder()
325                 if (thisElement != null) {
326                         thisElement.children().each() {
327                                 String nodeAsText = removeXmlPreamble(XmlUtil.serialize(it))
328                                 if (out.length() > 0) {
329                                         out.append(System.lineSeparator())
330                                 }
331                                 out.append(nodeAsText)
332                         }
333                 }
334                 return out.toString();
335         }
336
337         /**
338          * Encodes a value so it can be used inside an XML text element.
339          *
340          * <b>Will double encode</b>
341          * @param s the string to encode
342          * @return the encoded string
343          */
344         public static String xmlEscape(Object value) {
345                 return XmlTool.encode(value)
346         }
347
348         /**
349          * Removes the preamble, if present, from an XML document.
350          * Also, for historical reasons, this also trims leading and trailing
351          * whitespace from the resulting document.  TODO: remove the trimming
352          * and fix unit tests that depend on EXACT xml format.
353          * @param xml the XML document
354          * @return a possibly modified document
355          */
356         public String removeXmlPreamble(def xml) {
357                 if (xml == null) {
358                         return null
359                 }
360
361                 return XmlTool.removePreamble(xml).trim()
362         }
363
364         /**
365          * Removes namespaces and namespace declarations from an XML document.
366          * @param xml the XML document
367          * @return a possibly modified document
368          */
369         public String removeXmlNamespaces(def xml) {
370                 return XmlTool.removeNamespaces(xml);
371         }
372
373         /**
374          * Use formatXml instead.  Note: this method inserts an XML preamble.
375          */
376         @Deprecated
377         def formatXML(xmlInput) {
378                 def parseXml = null
379                 def formatXml = null
380                 if (xmlInput !=null) {
381                         parseXml = new XmlParser().parseText(xmlInput)
382                         formatXml = XmlUtil.serialize(parseXml)
383                 }
384         }
385
386         /**
387          * Reformats an XML document. The result will not contain an XML preamble
388          * or a trailing newline.
389          * @param xml the XML document
390          * @return a reformatted document
391          */
392         public String formatXml(def xml) {
393                 return XmlTool.normalize(xml);
394         }
395
396         // build single elements
397         def buildElements(xmlInput, elementList, parentName) {
398                 String var = ""
399                 def xmlBuild = ""
400                 if (parentName != "") {
401                    xmlBuild += "<tns2:"+parentName+">"
402                 }
403                 if (xmlInput != null) {
404                            for (element in elementList) {
405                               def xml= new XmlSlurper().parseText(xmlInput)
406                               var = xml.'**'.find {it.name() == element}
407                                   if (var != null) {
408                                  xmlBuild += "<tns2:"+element+">"+var.toString()+"</tns2:"+element+">"
409                                   }
410                            }
411                 }
412                 if (parentName != "") {
413                    xmlBuild += "</tns2:"+parentName+">"
414                 }
415                 return xmlBuild
416         }
417
418         // build the Unbounded elements
419         def buildElementsUnbounded(xmlInput, elementList, parentName) {
420                 def varParents = ""
421                 def var = ""
422                 def xmlBuildUnbounded = ""
423                 if (xmlInput != null) {
424                         def xml= new XmlSlurper().parseText(xmlInput)
425                         varParents = xml.'**'.findAll {it.name() == parentName}
426                         //println " Unbounded ${parentName} - varParent.Size() - " + varParents.size()
427                         for (i in 0..varParents.size()-1) {
428                                 if (parentName != "") {
429                                         xmlBuildUnbounded += "<tns2:"+parentName+">"
430                                  }
431                                 for (element in elementList) {
432                                         var = varParents[i].'*'.find {it.name() == element}
433                                    if (var != null) {
434                                           xmlBuildUnbounded += "<tns2:"+element+">"+var.toString()+"</tns2:"+element+">"
435                                           //println " i = " + i + ", element: " + element + " = " + var.toString()
436                                    }
437                                 }
438                                 if (parentName != "") {
439                                         xmlBuildUnbounded += "</tns2:"+parentName+">"
440                                  }
441                         }
442                 }
443                 return xmlBuildUnbounded
444          }
445
446         // Build l2-homing-information
447         def buildL2HomingInformation(xmlInput) {
448                 def elementsL2HomingList = ["evc-name", "topology", "preferred-aic-clli","aic-version"]
449                 def rebuildL2Home = ''
450                 if (xmlInput != null) {
451                         rebuildL2Home = buildElements(xmlInput, elementsL2HomingList, "l2-homing-information")
452                 }
453                 return rebuildL2Home
454         }
455
456         // Build internet-evc-access-information
457         def buildInternetEvcAccessInformation(xmlInput) {
458                 def elementsInternetEvcAccessInformationList = ["internet-evc-speed-value", "internet-evc-speed-units", "ip-version"]
459                 def rebuildInternetEvcAccess = ''
460                 if (xmlInput != null) {
461                         rebuildInternetEvcAccess = buildElements(xmlInput, elementsInternetEvcAccessInformationList, "internet-evc-access-information")
462                 }
463                 return rebuildInternetEvcAccess
464         }
465
466         // Build ucpe-vms-service-information
467         def buildUcpeVmsServiceInformation(xmlInput) {
468                 def rebuildUcpeVmsServiceInformation = ''
469                 if (xmlInput != null) {
470                         def ucpeVmsServiceInformation = getNodeXml(xmlInput, "ucpe-vms-service-information").drop(38).trim()
471                         rebuildUcpeVmsServiceInformation = "<tns2:ucpe-vms-service-information>"
472                         // transport-service-information
473                         rebuildUcpeVmsServiceInformation += "<tns2:transport-service-information>"
474                         def transportServiceInformation = getNodeXml(ucpeVmsServiceInformation, "transport-service-information").drop(38).trim()
475                         def elementsTransportServiceInformationList = ["transport-service-type"]
476                         rebuildUcpeVmsServiceInformation += buildElements(transportServiceInformation, elementsTransportServiceInformationList, "")
477                         try { // optional
478                                 def accessCircuitInfoList = ["access-circuit-id", "dual-mode"]
479                                 rebuildUcpeVmsServiceInformation += buildElementsUnbounded(transportServiceInformation, accessCircuitInfoList, "access-circuit-info")
480                         } catch (Exception e) {
481                            log("ERROR", " Optional - Exception ACCESS-CIRCUIT-INFO - 'access-circuit-info' ")
482                         }
483                         rebuildUcpeVmsServiceInformation += "</tns2:transport-service-information>"
484                         // ucpe-information
485                         def elementsUcpeInformationList = ["ucpe-host-name", "ucpe-activation-code", "out-of-band-management-modem" ]
486                         rebuildUcpeVmsServiceInformation += buildElements(ucpeVmsServiceInformation, elementsUcpeInformationList, "ucpe-information")
487                         // vnf-list
488                         rebuildUcpeVmsServiceInformation += "<tns2:vnf-list>"
489                         def vnfListList = ["vnf-instance-id", "vnf-sequence-number", "vnf-type", "vnf-vendor", "vnf-model", "vnf-id", "prov-status", "operational-state", "orchestration-status", "equipment-role" ]
490                         rebuildUcpeVmsServiceInformation += buildElementsUnbounded(ucpeVmsServiceInformation, vnfListList, "vnf-information")
491                         rebuildUcpeVmsServiceInformation += "</tns2:vnf-list>"
492                         rebuildUcpeVmsServiceInformation += "</tns2:ucpe-vms-service-information>"
493                 }
494                 log("DEBUG", " rebuildUcpeVmsServiceInformation - " + rebuildUcpeVmsServiceInformation)
495                 return rebuildUcpeVmsServiceInformation
496         }
497
498     // Build internet-service-change-details
499         def buildInternetServiceChangeDetails(xmlInput) {
500                 def rebuildInternetServiceChangeDetails = ""
501                 if (xmlInput != null) {
502                     try { // optional
503                                 def internetServiceChangeDetails = getNodeXml(xmlInput, "internet-service-change-details").drop(38).trim()
504                                 rebuildInternetServiceChangeDetails = "<tns:internet-service-change-details>"
505                                 rebuildInternetServiceChangeDetails += buildElements(internetServiceChangeDetails, ["internet-evc-speed-value"], "")
506                                 rebuildInternetServiceChangeDetails += buildElements(internetServiceChangeDetails, ["internet-evc-speed-units"], "")
507                                 rebuildInternetServiceChangeDetails += buildElements(internetServiceChangeDetails, ["v4-vr-lan-address"], "")
508                                 rebuildInternetServiceChangeDetails += buildElements(internetServiceChangeDetails, ["v4-vr-lan-prefix-length"], "")
509                                 try { // optional
510                                    def tProvidedV4LanPublicPrefixesChangesList = ["request-index", "v4-next-hop-address", "v4-lan-public-prefix", "v4-lan-public-prefix-length"]
511                                    rebuildInternetServiceChangeDetails += buildElementsUnbounded(internetServiceChangeDetails, tProvidedV4LanPublicPrefixesChangesList, "t-provided-v4-lan-public-prefixes")
512                                 } catch (Exception e) {
513                                    log("ERROR"," Optional - Exception in INTERNET-SERVICE-CHANGE-DETAILS 't-provided-v4-lan-public-prefixes ")
514                             }
515                                 try { // optional
516                                   def tProvidedV6LanPublicPrefixesChangesList = ["request-index", "v6-next-hop-address", "v6-lan-public-prefix", "v6-lan-public-prefix-length"]
517                                   rebuildInternetServiceChangeDetails += buildElementsUnbounded(internetServiceChangeDetails, tProvidedV6LanPublicPrefixesChangesList, "t-provided-v6-lan-public-prefixes")
518                                 } catch (Exception e) {
519                                         log("ERROR"," Optional - Exception INTERNET-SERVICE-CHANGE-DETAILS 't-provided-v6-lan-public-prefixes ")
520                                 }
521                                 rebuildInternetServiceChangeDetails += "</tns:internet-service-change-details>"
522                         } catch (Exception e) {
523                                 log("ERROR", " Optional - Exception INTERNET-SERVICE-CHANGE-DETAILS 'internet-service-change-details' ")
524                         }
525                 }
526             return rebuildInternetServiceChangeDetails
527         }
528
529         // Build vr-lan
530         def buildVrLan(xmlInput) {
531
532                 def rebuildVrLan = ''
533                 if (xmlInput != null) {
534
535                         rebuildVrLan = "<tns2:vr-lan>"
536                         def vrLan = getNodeXml(xmlInput, "vr-lan").drop(38).trim()
537                         rebuildVrLan += buildElements(vrLan, ["routing-protocol"], "")
538
539                         // vr-lan-interface
540                         def rebuildVrLanInterface = "<tns2:vr-lan-interface>"
541                         def vrLanInterface = getNodeXml(vrLan, "vr-lan-interface").drop(38).trim()
542                         rebuildVrLanInterface += buildVrLanInterfacePartial(vrLanInterface)
543
544                          // dhcp
545                          def dhcp = getNodeXml(vrLan, "dhcp").drop(38).trim()
546                          def rebuildDhcp = buildDhcp(dhcp)
547                          rebuildVrLanInterface += rebuildDhcp
548
549                          // pat
550                          def pat = getNodeXml(vrLan, "pat").drop(38).trim()
551                          def rebuildPat = buildPat(pat)
552                          rebuildVrLanInterface += rebuildPat
553
554                          // nat
555                          def rebuildNat = ""
556                          try { // optional
557                                 def nat = getNodeXml(vrLan, "nat").drop(38).trim()
558                                 rebuildNat = buildNat(nat)
559                          } catch (Exception e) {
560                                  log("ERROR", " Optional - Exception 'nat' ")
561                          }
562                          rebuildVrLanInterface += rebuildNat
563
564                          // firewall-lite
565                          def firewallLite = getNodeXml(vrLan, "firewall-lite").drop(38).trim()
566                          def rebuildFirewallLite = buildFirewallLite(firewallLite)
567                          rebuildVrLanInterface += rebuildFirewallLite
568
569                          // static-routes
570                          def rebuildStaticRoutes = ""
571                          try { // optional
572                                  def staticRoutes = getNodeXml(vrLan, "static-routes").drop(38).trim()
573                                  rebuildStaticRoutes = buildStaticRoutes(staticRoutes)
574                         } catch (Exception e) {
575                                  log("ERROR", " Optional - Exception 'static-routes' ")
576                         }
577                         rebuildVrLanInterface += rebuildStaticRoutes
578
579                    rebuildVrLan += rebuildVrLanInterface
580                    rebuildVrLan += "</tns2:vr-lan-interface>"
581                    rebuildVrLan += "</tns2:vr-lan>"
582
583                 }
584                 log("DEBUG", " rebuildVrLan - " + rebuildVrLan)
585                 return rebuildVrLan
586         }
587
588         // Build vr-lan-interface
589         def buildVrLanInterfacePartial(xmlInput) {
590                 def rebuildingVrLanInterface = ''
591                 if (xmlInput != null) {
592                         def vrLanInterfaceList = ["vr-designation", "v4-vr-lan-prefix", "v4-vr-lan-address", "v4-vr-lan-prefix-length", "v6-vr-lan-prefix", "v6-vr-lan-address", "v6-vr-lan-prefix-length", "v4-vce-loopback-address", "v6-vce-wan-address"]
593                         rebuildingVrLanInterface += buildElements(xmlInput, vrLanInterfaceList, "")
594                         rebuildingVrLanInterface += "<tns2:v4-public-lan-prefixes>"
595                         try { // optional
596                                 def tProvidedV4LanPublicPrefixes = getNodeXml(xmlInput, "v4-public-lan-prefixes").drop(38).trim()
597                                 def tProvidedV4LanPublicPrefixesList = ["request-index", "v4-next-hop-address", "v4-lan-public-prefix", "v4-lan-public-prefix-length" ]
598                                 rebuildingVrLanInterface += buildElementsUnbounded(xmlInput, tProvidedV4LanPublicPrefixesList, "t-provided-v4-lan-public-prefixes")
599                         } catch (Exception ex) {
600                                 log("ERROR", " Optional - Exception VR-LAN INTERFACE 'v4-public-lan-prefixes' ")
601                         }
602                         rebuildingVrLanInterface += "</tns2:v4-public-lan-prefixes>"
603                         rebuildingVrLanInterface += "<tns2:v6-public-lan-prefixes>"
604                         try { // optional
605                                 def tProvidedV6LanPublicPrefixes = getNodeXml(xmlInput, "v6-public-lan-prefixes").drop(38).trim()
606                                 def tProvidedV6LanPublicPrefixesList = ["request-index", "v6-next-hop-address", "v6-lan-public-prefix", "v6-lan-public-prefix-length" ]
607                                 rebuildingVrLanInterface += buildElementsUnbounded(xmlInput, tProvidedV6LanPublicPrefixesList, "t-provided-v6-lan-public-prefixes")
608                         } catch (Exception e) {
609                                 log("ERROR", " Optional - Exception VR-LAN INTERFACE 'v6-public-lan-prefixes' ")
610                         }
611                         rebuildingVrLanInterface += "</tns2:v6-public-lan-prefixes>"
612                 }
613                 log("DEBUG", " rebuildingVrLanInterface - " + rebuildingVrLanInterface)
614                 return rebuildingVrLanInterface
615         }
616
617         // Build dhcp
618         def buildDhcp(xmlInput) {
619                 def rebuildingDhcp = ''
620                 if (xmlInput != null) {
621                         def dhcpData = new XmlSlurper().parseText(xmlInput)
622                         rebuildingDhcp = "<tns2:dhcp>"
623                         def dhcpList1 = ["v4-dhcp-server-enabled", "v6-dhcp-server-enabled", "use-v4-default-pool", "v4-dhcp-default-pool-prefix", "v4-dhcp-default-pool-prefix-length"]
624                         rebuildingDhcp += buildElements(xmlInput, dhcpList1, "")
625                         try { // optional
626                                 def excludedV4DhcpAddressesFromDefaultPoolList = ["excluded-v4-address"]
627                                 rebuildingDhcp += buildElementsUnbounded(xmlInput, excludedV4DhcpAddressesFromDefaultPoolList, "excluded-v4-dhcp-addresses-from-default-pool")
628                         } catch (Exception e) {
629                                 log("ERROR", " Optional - Exception DHCP 'excluded-v4-dhcp-addresses-from-default-pool' ")
630                         }
631                         try { // optional
632                                 def v4DhcpPools = dhcpData.'**'.findAll {it.name() == "v4-dhcp-pools"}
633                                 def v4DhcpPoolsSize = v4DhcpPools.size()
634                                 // println " v4DhcpPoolsSize = " + v4DhcpPools.size()
635                                 for (i in 0..v4DhcpPoolsSize-1) {
636                                         def v4DhcpPool = v4DhcpPools[i]
637                                         def v4DhcpPoolXml = XmlUtil.serialize(v4DhcpPool)
638                                         rebuildingDhcp += "<tns2:v4-dhcp-pools>"
639                                         def v4DhcpPoolsList1 = ["v4-dhcp-pool-prefix", "v4-dhcp-pool-prefix-length" ]
640                                         rebuildingDhcp += buildElements(v4DhcpPoolXml, v4DhcpPoolsList1, "")
641                                         try { // optional
642                                            def excludedV4AddressesList = ["excluded-v4-address"]
643                                            rebuildingDhcp += buildElementsUnbounded(v4DhcpPoolXml, excludedV4AddressesList, "excluded-v4-addresses")
644                                         } catch (Exception e) {
645                                            log("ERROR", " Optional - Exception DHCP 'excluded-v4-addresses' ")
646                                         }
647                                         def v4DhcpPoolsList2 = ["v4-dhcp-relay-gateway-address", "v4-dhcp-relay-next-hop-address"]
648                                         rebuildingDhcp += buildElements(v4DhcpPoolXml, v4DhcpPoolsList2, "")
649                                         rebuildingDhcp += "</tns2:v4-dhcp-pools>"
650                                  }
651                          } catch (Exception e) {
652                                   log("ERROR"," Optional - Exception DHCP 'v4-dhcp-pools' ")
653                          }
654                          def dhcpList2 = ["use-v6-default-pool", "v6-dhcp-default-pool-prefix", "v6-dhcp-default-pool-prefix-length"]
655                          rebuildingDhcp += buildElements(xmlInput, dhcpList2, "")
656                          try { // optional
657                                  def excludedV6DhcpAddressesFromDdefaultPoolList = ["excluded-v6-address"]
658                                  rebuildingDhcp += buildElementsUnbounded(xmlInput, excludedV6DhcpAddressesFromDdefaultPoolList, "excluded-v6-dhcp-addresses-from-default-pool")
659                          } catch (Exception e) {
660                            log("ERROR", " Optional - Exception DHCP 'excluded-v6-dhcp-addresses-from-default-pool' ")
661                          }
662                          try { // optional
663                                  def v6DhcpPools = dhcpData.'**'.findAll {it.name() == "v6-dhcp-pools"}
664                                  def v6DhcpPoolsSize = v6DhcpPools.size()
665                                  //println " v6DhcpPoolsSize = " + v6DhcpPools.size()
666                                  for (i in 0..v6DhcpPoolsSize-1) {
667                                         def v6DhcpPool = v6DhcpPools[i]
668                                         def v6DhcpPoolXml = XmlUtil.serialize(v6DhcpPool)
669                                         rebuildingDhcp += "<tns2:v6-dhcp-pools>"
670                                         def v6DhcpPoolsList1 = ["v6-dhcp-pool-prefix", "v6-dhcp-pool-prefix-length"]
671                                         rebuildingDhcp += buildElements(v6DhcpPoolXml, v6DhcpPoolsList1, "")
672                                         try { // optional
673                                                 def excludedV6AddressesList = ["excluded-v6-address"]
674                                                 rebuildingDhcp += buildElementsUnbounded(v6DhcpPoolXml, excludedV6AddressesList, "excluded-v6-addresses")
675                                         } catch (Exception e) {
676                                                          log("ERROR", " Optional - Exception DHCP 'excluded-v6-addresses' ")
677                                         }
678                                         def v6DhcpPoolsList2 = ["v6-dhcp-relay-gateway-address", "v6-dhcp-relay-next-hop-address"]
679                                         rebuildingDhcp += buildElements(v6DhcpPoolXml, v6DhcpPoolsList2, "")
680                                         rebuildingDhcp += "</tns2:v6-dhcp-pools>"
681                                  }
682                          } catch (Exception e) {
683                                  log("ERROR", " Optional - Exception DHCP 'v6-dhcp-pools' ")
684                          }
685                          rebuildingDhcp += "</tns2:dhcp>"
686                 }
687                 log("DEBUG", " rebuildingDhcp - " + rebuildingDhcp)
688                 return rebuildingDhcp
689         }
690
691         // Build pat
692         def buildPat(xmlInput) {
693                  def rebuildingPat = ''
694                  if (xmlInput != null) {
695                          rebuildingPat = "<tns2:pat>"
696                          def patList = ["v4-pat-enabled", "use-v4-default-pool", "v4-pat-default-pool-prefix", "v4-pat-default-pool-prefix-length"]
697                          rebuildingPat += buildElements(xmlInput, patList, "")
698                          try { // optional
699                                  def v4PatPools = getNodeXml(xmlInput, "v4-pat-pools").drop(38).trim()
700                                  def v4PatPoolsList = ["v4-pat-pool-prefix", "v4-pat-pool-prefix-length", "v4-pat-pool-next-hop-address"]
701                                  rebuildingPat += buildElementsUnbounded(xmlInput, v4PatPoolsList, "v4-pat-pools")
702                          } catch (Exception e) {
703                                 log("ERROR", " Optional - Exception 'v4-pat-pool-next-hop-address' ")
704                          }
705                          rebuildingPat += "</tns2:pat>"
706                  }
707                  log("DEBUG", " rebuildingPat - " + rebuildingPat)
708              return rebuildingPat
709     }
710
711         // Build nat
712         def buildNat(xmlInput) {
713                 def rebuildingNat = ''
714                 if (xmlInput != null) {
715                         rebuildingNat = "<tns2:nat>"
716                         rebuildingNat += buildElements(xmlInput, ["v4-nat-enabled"], "")
717                         try { // optional
718                          def v4NatMappingEntries = getNodeXml(xmlInput, "v4-nat-mapping-entries").drop(38).trim()
719                          def v4NatMappingEntriesList = ["v4-nat-internal", "v4-nat-next-hop-address", "v4-nat-external"]
720                          rebuildingNat += buildElementsUnbounded(xmlInput, v4NatMappingEntriesList, "v4-nat-mapping-entries")
721                         } catch (Exception e) {
722                            log("ERROR", " Optional - Exception 'v4-nat-external' ")
723                         }
724                         rebuildingNat += "</tns2:nat>"
725                 }
726                 log("DEBUG", " rebuildingNat - " + rebuildingNat)
727             return rebuildingNat
728         }
729
730         // Build firewall-lite
731         def buildFirewallLite(xmlInput) {
732                 def rebuildingFirewallLite = ''
733
734                 if (xmlInput != null) {
735
736                         def firewallLiteData = new XmlSlurper().parseText(xmlInput)
737                         rebuildingFirewallLite = "<tns2:firewall-lite>"
738                         def firewallLiteList = ["stateful-firewall-lite-v4-enabled", "stateful-firewall-lite-v6-enabled"]
739                         rebuildingFirewallLite += buildElements(xmlInput, firewallLiteList, "")
740
741                          try { // optional
742                                  def v4FirewallPacketFilters = firewallLiteData.'**'.findAll {it.name() == "v4-firewall-packet-filters"}
743                                  def v4FirewallPacketFiltersSize = v4FirewallPacketFilters.size()
744                                  //println " v4FirewallPacketFiltersSize = " + v4FirewallPacketFilters.size()
745                                  for (i in 0..v4FirewallPacketFiltersSize-1) {
746                                def v4FirewallPacketFilter = v4FirewallPacketFilters[i]
747                                def v4FirewallPacketFilterXml = XmlUtil.serialize(v4FirewallPacketFilter)
748                                    rebuildingFirewallLite += "<tns2:v4-firewall-packet-filters>"
749                                    def v4FirewallPacketFiltersList = ["v4-firewall-prefix", "v4-firewall-prefix-length", "allow-icmp-ping"]
750                                    rebuildingFirewallLite += buildElements(v4FirewallPacketFilterXml, v4FirewallPacketFiltersList, "")
751                                    try {  // optional
752                                   def udpPortsList = ["port-number"]
753                                           rebuildingFirewallLite += buildElementsUnbounded(v4FirewallPacketFilterXml, udpPortsList, "udp-ports")
754                                    } catch (Exception e) {
755                                           log("ERROR", " Optional - Exception FIREWALL-LITE v4 'udp-ports' ")
756                                    }
757                                    try {  // optional
758                                           def tcpPortsList =  ["port-number"]
759                                           rebuildingFirewallLite += buildElementsUnbounded(v4FirewallPacketFilterXml, tcpPortsList, "tcp-ports")
760                                    } catch (Exception e) {
761                                       log("ERROR", " Optional - Exception FIREWALL-LITE v4 'tcp-ports' ")
762                                    }
763                                    rebuildingFirewallLite += "</tns2:v4-firewall-packet-filters>"
764                                  }
765                          } catch (Exception e) {
766                                  log("ERROR", " Optional - Exception FIREWALL-LITE 'v4-firewall-packet-filters' ")
767                          }
768
769                          try { // optional
770                                  def v6FirewallPacketFilters = firewallLiteData.'**'.findAll {it.name() == "v6-firewall-packet-filters"}
771                                  def v6FirewallPacketFiltersSize = v6FirewallPacketFilters.size()
772                                  //println " v6FirewallPacketFiltersSize = " + v6FirewallPacketFilters.size()
773                                  for (i in 0..v6FirewallPacketFiltersSize-1) {
774                                         def v6FirewallPacketFilter = v6FirewallPacketFilters[i]
775                                         def v6FirewallPacketFilterXml = XmlUtil.serialize(v6FirewallPacketFilter)
776                                         rebuildingFirewallLite += "<tns2:v6-firewall-packet-filters>"
777                                         def v6FirewallPacketFiltersList = ["v6-firewall-prefix", "v6-firewall-prefix-length", "allow-icmp-ping"]
778                                         rebuildingFirewallLite += buildElements(v6FirewallPacketFilterXml, v6FirewallPacketFiltersList, "")
779                                         try { // optional
780                                                 def udpPortsList = ["port-number"]
781                                                 rebuildingFirewallLite += buildElementsUnbounded(v6FirewallPacketFilterXml, udpPortsList, "udp-ports")
782                                         } catch (Exception e) {
783                                       log("ERROR", " Optional - Exception FIREWALL-LITE v6 'udp-ports' ")
784                                         }
785                                         try { // optional
786                                                 def tcpPortsList =  ["port-number"]
787                                                 rebuildingFirewallLite += buildElementsUnbounded(v6FirewallPacketFilterXml, tcpPortsList, "tcp-ports")
788                                         } catch (Exception e) {
789                                         log("ERROR", " Optional - Exception FIREWALL-LITE v6 'tcp-ports' ")
790                                         }
791                                rebuildingFirewallLite += "</tns2:v6-firewall-packet-filters>"
792                                  }
793                          } catch (Exception e) {
794                                  log("ERROR", " Optional - Exception FIREWALL-LITE 'v6-firewall-packet-filters' ")
795                          }
796                          rebuildingFirewallLite+= "</tns2:firewall-lite>"
797                 }
798                 log("DEBUG", " rebuildingFirewallLite - " + rebuildingFirewallLite)
799                 return rebuildingFirewallLite
800      }
801
802         def buildStaticRoutes(xmlInput) {
803                 def rebuildingStaticRoutes = ''
804                 if (xmlInput != null) {
805                         rebuildingStaticRoutes = "<tns2:static-routes>"
806                         def v4StaticRouteslist = ["v4-static-route-prefix","v4-static-route-prefix-length", "v4-next-hop-address"]
807                         rebuildingStaticRoutes += buildElementsUnbounded(xmlInput, v4StaticRouteslist, "v4-static-routes")
808                         def v6StaticRouteslist = ["v6-static-route-prefix","v6-static-route-prefix-length", "v6-next-hop-address"]
809                         rebuildingStaticRoutes += buildElementsUnbounded(xmlInput, v6StaticRouteslist, "v6-static-routes")
810                         rebuildingStaticRoutes += "</tns2:static-routes>"
811                 }
812                 log("DEBUG", " rebuildingStaticRoutes - " + rebuildingStaticRoutes)
813                 return rebuildingStaticRoutes
814         }
815
816         public String generateCurrentTimeInUtc(){
817                 final  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
818                 sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
819                 final String utcTime = sdf.format(new Date());
820                 return utcTime;
821         }
822
823         public String generateCurrentTimeInGMT(){
824                 final  SimpleDateFormat sdf = new SimpleDateFormat("E, d MMM yyyy h:m:s z");
825                 sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
826                 final String utcTime = sdf.format(new Date());
827                 return utcTime;
828         }
829
830
831         /**
832          * @param encryptedAuth: encrypted credentials from urn properties
833          * @param msoKey: key to use to decrypt from urn properties
834          * @return base 64 encoded basic auth credentials
835          */
836         def getBasicAuth(encryptedAuth, msoKey){
837                 if ((encryptedAuth == null || encryptedAuth.isEmpty()) || (msoKey == null || msoKey.isEmpty()))
838                         return null
839                 try {
840                         def auth = decrypt(encryptedAuth, msoKey)
841                         byte[] encoded = Base64.encodeBase64(auth.getBytes())
842                         String encodedString = new String(encoded)
843                         encodedString = "Basic " + encodedString
844                         return encodedString
845                 } catch (Exception ex) {
846                         log("ERROR", "Unable to encode basic auth")
847                         throw ex
848                 }
849         }
850
851         def encrypt(toEncrypt, msokey){
852                 try {
853                         String result = CryptoUtils.encrypt(toEncrypt, msokey);
854                         return result
855                 }
856                 catch (Exception e) {
857                         log("ERROR", "Failed to encrypt credentials")
858                 }
859         }
860
861         def decrypt(toDecrypt, msokey){
862                 try {
863                         String result = CryptoUtils.decrypt(toDecrypt, msokey);
864                         return result
865                 }
866                 catch (Exception e) {
867                         log("ERROR", "Failed to decrypt credentials")
868                         throw e
869                 }
870         }
871
872         /**
873          * Return URL with qualified host name (if any) or urn mapping
874          * @param  String url from urn mapping
875          * @return String url with qualified host name
876          */
877         public String getQualifiedHostNameForCallback(String urnCallbackUrl) {
878                 def callbackUrlToUse = urnCallbackUrl
879                 try{
880                         //swap host name with qualified host name from the jboss properties
881                         def qualifiedHostName = System.getProperty("jboss.qualified.host.name")
882                         if(qualifiedHostName!=null){
883                                 log("DEBUG", "qualifiedHostName:\n" + qualifiedHostName)
884                                 callbackUrlToUse = callbackUrlToUse.replaceAll("(http://)(.*)(:28080*)", {orig, first, torepl, last -> "${first}${qualifiedHostName}${last}"})
885                         }
886                 }catch(Exception e){
887                         logger.debug("Unable to grab qualified host name, using what's in urn properties for callbackurl. Exception was: {}", e.getMessage(), e)
888                 }
889                 return callbackUrlToUse
890
891         }
892
893         /**
894          * Retrieves text context of the element if the element exists, returns empty string otherwise
895          * @param com.sun.org.apache.xerces.internal.dom.DeferredElementNSImpl element to parse
896          * param String tagName tagName
897          * @return String text content of the element
898          */
899          public String getElementText(Element element, String tagName) {
900                 String text = ""
901                 org.w3c.dom.NodeList nodeList = element.getElementsByTagNameNS("*", tagName)
902                 if (nodeList != null && nodeList.length > 0) {
903                         text = nodeList.item(0).getTextContent()
904                 }
905                 return text
906          }
907
908          /**
909           *
910           * Find the lowest unused module-index value in a given xml
911           */
912          public String getLowestUnusedIndex(String xml) {
913                  if (xml == null || xml.isEmpty()) {
914                          return "0"
915                  }
916                  def moduleIndexList = getMultNodes(xml, "module-index")
917                  if (moduleIndexList == null || moduleIndexList.size() == 0) {
918                          return "0"
919                  }
920
921                  def sortedModuleIndexList = moduleIndexList.sort{ a, b -> a as Integer <=> b as Integer}
922
923                  for (i in 0..sortedModuleIndexList.size()-1) {
924                          if (Integer.parseInt(sortedModuleIndexList[i]) != i) {
925                                  return i.toString()
926                          }
927                  }
928                  return sortedModuleIndexList.size().toString()
929          }
930         /**
931          * This utility checks if there is transaction id already present in MDC.
932          * If found, it returns same else creates new, sets in MDC for future use before returning
933          * @return String RequestId in UUID format.
934          */
935         public String getRequestID()
936         {
937                 String requestId = MDC.get("RequestId")
938                 if(requestId == null || requestId.isEmpty())
939                 {
940                         requestId = java.util.UUID.randomUUID()
941                         MDC.put("RequestId",requestId)
942                         log("DEBUG","MsoUtils - Created new RequestId: " + requestId)
943                 }
944                 else
945                 {
946                         log("DEBUG","MsoUtils - Using existing RequestId: " + requestId)
947                 }
948
949                 return requestId
950         }
951
952         /**
953          * Remove all the empty nodes and attributes from the within the given node
954          * @param node
955          * @return true if all empty nodes and attributes were removed.
956          */
957         public boolean cleanNode( Node node ) {
958                 node.attributes().with { a ->
959                         a.findAll { !it.value }.each { a.remove( it.key ) }
960                 }
961                 node.children().with { kids ->
962                         kids.findAll { it instanceof Node ? !cleanNode( it ) : false }
963                                         .each { kids.remove( it ) }
964                 }
965                 node.attributes() || node.children() || node.text()
966         }
967
968         /**
969          *
970          * @param xml
971          * @return String representation of xml after removing the empty nodes and attributes
972          */
973         public String cleanNode(String xmlString) {
974                 def xml = new XmlParser(false, false).parseText(xmlString)
975                 cleanNode(xml)
976                 return XmlUtil.serialize(xml)
977         }
978 }