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