Updated to use vnfOperationalEnvironmentId
[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.BPMNLogger
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                 }
277                                 
278                         return myNodes
279                 }else{
280                         return null
281                 }
282         }
283         
284         def getPBGFList(xmlInput){
285                 getPBGFList("false", xmlInput)
286         }
287         
288         def getMetaVal(node, name){
289                 try{
290                         return node.'**'.find {it.metaname.text() == name}.metaval.text()
291                 }catch(Exception e){
292                         return null
293                 }
294         }
295
296         def log(logmode,logtxt,isDebugLogEnabled="false"){
297                 if ("INFO"==logmode) {
298                         logger.info(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, logtxt, "BPMN");
299                 } else if ("WARN"==logmode) {
300                         logger.warn ("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_WARNING.toString(), logtxt, "BPMN",
301                                         ErrorCode.UnknownError.getValue(), logtxt);
302                 } else if ("ERROR"==logmode) {
303                     logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), logtxt, "BPMN",
304                                         ErrorCode.UnknownError.getValue(), logtxt);
305
306                 } else {
307                         BPMNLogger.debug(isDebugLogEnabled, logtxt);
308                 }
309         }
310
311         // headers: header - name-value
312         def getHeaderNameValue(xmlInput, nameAttribute){
313                 def rtn=null
314                 if(xmlInput!=null){
315                         def xml= new XmlSlurper().parseText(xmlInput)
316                         rtn= xml.'**'.find {header->header.'@name'.text() == nameAttribute}.'@value'
317                 }
318                 return rtn
319         }
320         
321         /**
322          * Gets the children of the specified element.
323          */
324         public String getChildNodes(xmlInput, element) {
325                 def xml= new XmlSlurper().parseText(xmlInput)
326                 def thisElement = xml.'**'.find {it.name() == element}
327                 StringBuilder out = new StringBuilder()
328                 if (thisElement != null) {
329                         thisElement.children().each() {
330                                 String nodeAsText = removeXmlPreamble(XmlUtil.serialize(it))
331                                 if (out.length() > 0) {
332                                         out.append(System.lineSeparator())
333                                 }
334                                 out.append(nodeAsText)
335                         }
336                 }
337                 return out.toString();
338         }
339         
340         /**
341          * Encodes a value so it can be used inside an XML text element.
342          * 
343          * <b>Will double encode</b>
344          * @param s the string to encode
345          * @return the encoded string
346          */
347         public static String xmlEscape(Object value) {
348                 return XmlTool.encode(value)
349         }
350         
351         /**
352          * Removes the preamble, if present, from an XML document.
353          * Also, for historical reasons, this also trims leading and trailing
354          * whitespace from the resulting document.  TODO: remove the trimming
355          * and fix unit tests that depend on EXACT xml format.
356          * @param xml the XML document
357          * @return a possibly modified document
358          */
359         public String removeXmlPreamble(def xml) {
360                 if (xml == null) {
361                         return null
362                 }
363
364                 return XmlTool.removePreamble(xml).trim()
365         }
366
367         /**
368          * Removes namespaces and namespace declarations from an XML document.
369          * @param xml the XML document
370          * @return a possibly modified document
371          */
372         public String removeXmlNamespaces(def xml) {
373                 return XmlTool.removeNamespaces(xml);
374         }
375
376         /**
377          * Use formatXml instead.  Note: this method inserts an XML preamble.
378          */
379         @Deprecated
380         def formatXML(xmlInput) {
381                 def parseXml = null
382                 def formatXml = null
383                 if (xmlInput !=null) {
384                         parseXml = new XmlParser().parseText(xmlInput)
385                         formatXml = XmlUtil.serialize(parseXml)
386                 }
387         }
388
389         /**
390          * Reformats an XML document. The result will not contain an XML preamble
391          * or a trailing newline.
392          * @param xml the XML document
393          * @return a reformatted document
394          */
395         public String formatXml(def xml) {
396                 return XmlTool.normalize(xml);
397         }
398         
399         // build single elements
400         def buildElements(xmlInput, elementList, parentName) {
401                 String var = ""
402                 def xmlBuild = ""
403                 if (parentName != "") {
404                    xmlBuild += "<tns2:"+parentName+">"
405                 }   
406                 if (xmlInput != null) {
407                            for (element in elementList) {
408                               def xml= new XmlSlurper().parseText(xmlInput)
409                               var = xml.'**'.find {it.name() == element}
410                                   if (var != null) {
411                                  xmlBuild += "<tns2:"+element+">"+var.toString()+"</tns2:"+element+">"
412                                   } 
413                            }
414                 }
415                 if (parentName != "") {
416                    xmlBuild += "</tns2:"+parentName+">"
417                 }   
418                 return xmlBuild
419         }
420         
421         // build the Unbounded elements
422         def buildElementsUnbounded(xmlInput, elementList, parentName) {
423                 def varParents = ""
424                 def var = ""
425                 def xmlBuildUnbounded = ""
426                 if (xmlInput != null) {
427                         def xml= new XmlSlurper().parseText(xmlInput)
428                         varParents = xml.'**'.findAll {it.name() == parentName}
429                         //println " Unbounded ${parentName} - varParent.Size() - " + varParents.size()
430                         for (i in 0..varParents.size()-1) {
431                                 if (parentName != "") {
432                                         xmlBuildUnbounded += "<tns2:"+parentName+">"
433                                  }
434                                 for (element in elementList) {
435                                         var = varParents[i].'*'.find {it.name() == element}
436                                    if (var != null) {
437                                           xmlBuildUnbounded += "<tns2:"+element+">"+var.toString()+"</tns2:"+element+">"
438                                           //println " i = " + i + ", element: " + element + " = " + var.toString()
439                                    }
440                                 }
441                                 if (parentName != "") {
442                                         xmlBuildUnbounded += "</tns2:"+parentName+">"
443                                  }
444                         }
445                 }
446                 return xmlBuildUnbounded
447          }
448         
449         // Build l2-homing-information
450         def buildL2HomingInformation(xmlInput) {
451                 def elementsL2HomingList = ["evc-name", "topology", "preferred-aic-clli","aic-version"]
452                 def rebuildL2Home = ''
453                 if (xmlInput != null) {
454                         rebuildL2Home = buildElements(xmlInput, elementsL2HomingList, "l2-homing-information")
455                 }
456                 return rebuildL2Home
457         }
458         
459         // Build internet-evc-access-information
460         def buildInternetEvcAccessInformation(xmlInput) {
461                 def elementsInternetEvcAccessInformationList = ["internet-evc-speed-value", "internet-evc-speed-units", "ip-version"]
462                 def rebuildInternetEvcAccess = ''
463                 if (xmlInput != null) {
464                         rebuildInternetEvcAccess = buildElements(xmlInput, elementsInternetEvcAccessInformationList, "internet-evc-access-information")
465                 }
466                 return rebuildInternetEvcAccess
467         }
468         
469         // Build ucpe-vms-service-information
470         def buildUcpeVmsServiceInformation(xmlInput) {
471                 def rebuildUcpeVmsServiceInformation = ''
472                 if (xmlInput != null) {
473                         def ucpeVmsServiceInformation = getNodeXml(xmlInput, "ucpe-vms-service-information").drop(38).trim()
474                         rebuildUcpeVmsServiceInformation = "<tns2:ucpe-vms-service-information>"
475                         // transport-service-information
476                         rebuildUcpeVmsServiceInformation += "<tns2:transport-service-information>"
477                         def transportServiceInformation = getNodeXml(ucpeVmsServiceInformation, "transport-service-information").drop(38).trim()
478                         def elementsTransportServiceInformationList = ["transport-service-type"]
479                         rebuildUcpeVmsServiceInformation += buildElements(transportServiceInformation, elementsTransportServiceInformationList, "")
480                         try { // optional
481                                 def accessCircuitInfoList = ["access-circuit-id", "dual-mode"]
482                                 rebuildUcpeVmsServiceInformation += buildElementsUnbounded(transportServiceInformation, accessCircuitInfoList, "access-circuit-info")
483                         } catch (Exception e) {
484                            log("ERROR", " Optional - Exception ACCESS-CIRCUIT-INFO - 'access-circuit-info' ")
485                         }
486                         rebuildUcpeVmsServiceInformation += "</tns2:transport-service-information>"
487                         // ucpe-information
488                         def elementsUcpeInformationList = ["ucpe-host-name", "ucpe-activation-code", "out-of-band-management-modem" ]
489                         rebuildUcpeVmsServiceInformation += buildElements(ucpeVmsServiceInformation, elementsUcpeInformationList, "ucpe-information")
490                         // vnf-list
491                         rebuildUcpeVmsServiceInformation += "<tns2:vnf-list>"
492                         def vnfListList = ["vnf-instance-id", "vnf-sequence-number", "vnf-type", "vnf-vendor", "vnf-model", "vnf-id", "prov-status", "operational-state", "orchestration-status", "equipment-role" ]
493                         rebuildUcpeVmsServiceInformation += buildElementsUnbounded(ucpeVmsServiceInformation, vnfListList, "vnf-information")
494                         rebuildUcpeVmsServiceInformation += "</tns2:vnf-list>"
495                         rebuildUcpeVmsServiceInformation += "</tns2:ucpe-vms-service-information>"
496                 }
497                 log("DEBUG", " rebuildUcpeVmsServiceInformation - " + rebuildUcpeVmsServiceInformation)
498                 return rebuildUcpeVmsServiceInformation
499         }
500         
501     // Build internet-service-change-details
502         def buildInternetServiceChangeDetails(xmlInput) {
503                 def rebuildInternetServiceChangeDetails = ""
504                 if (xmlInput != null) {
505                     try { // optional
506                                 def internetServiceChangeDetails = getNodeXml(xmlInput, "internet-service-change-details").drop(38).trim()
507                                 rebuildInternetServiceChangeDetails = "<tns:internet-service-change-details>"
508                                 rebuildInternetServiceChangeDetails += buildElements(internetServiceChangeDetails, ["internet-evc-speed-value"], "")
509                                 rebuildInternetServiceChangeDetails += buildElements(internetServiceChangeDetails, ["internet-evc-speed-units"], "")
510                                 rebuildInternetServiceChangeDetails += buildElements(internetServiceChangeDetails, ["v4-vr-lan-address"], "")
511                                 rebuildInternetServiceChangeDetails += buildElements(internetServiceChangeDetails, ["v4-vr-lan-prefix-length"], "")
512                                 try { // optional
513                                    def tProvidedV4LanPublicPrefixesChangesList = ["request-index", "v4-next-hop-address", "v4-lan-public-prefix", "v4-lan-public-prefix-length"]
514                                    rebuildInternetServiceChangeDetails += buildElementsUnbounded(internetServiceChangeDetails, tProvidedV4LanPublicPrefixesChangesList, "t-provided-v4-lan-public-prefixes")
515                                 } catch (Exception e) {
516                                    log("ERROR"," Optional - Exception in INTERNET-SERVICE-CHANGE-DETAILS 't-provided-v4-lan-public-prefixes ")
517                             }
518                                 try { // optional
519                                   def tProvidedV6LanPublicPrefixesChangesList = ["request-index", "v6-next-hop-address", "v6-lan-public-prefix", "v6-lan-public-prefix-length"]
520                                   rebuildInternetServiceChangeDetails += buildElementsUnbounded(internetServiceChangeDetails, tProvidedV6LanPublicPrefixesChangesList, "t-provided-v6-lan-public-prefixes")
521                                 } catch (Exception e) {
522                                         log("ERROR"," Optional - Exception INTERNET-SERVICE-CHANGE-DETAILS 't-provided-v6-lan-public-prefixes ")
523                                 }
524                                 rebuildInternetServiceChangeDetails += "</tns:internet-service-change-details>"
525                         } catch (Exception e) {
526                                 log("ERROR", " Optional - Exception INTERNET-SERVICE-CHANGE-DETAILS 'internet-service-change-details' ")
527                         }
528                 }
529             return rebuildInternetServiceChangeDetails
530         }               
531         
532         // Build vr-lan 
533         def buildVrLan(xmlInput) {
534                 
535                 def rebuildVrLan = ''
536                 if (xmlInput != null) {
537                         
538                         rebuildVrLan = "<tns2:vr-lan>"
539                         def vrLan = getNodeXml(xmlInput, "vr-lan").drop(38).trim()
540                         rebuildVrLan += buildElements(vrLan, ["routing-protocol"], "")
541                         
542                         // vr-lan-interface
543                         def rebuildVrLanInterface = "<tns2:vr-lan-interface>"
544                         def vrLanInterface = getNodeXml(vrLan, "vr-lan-interface").drop(38).trim()
545                         rebuildVrLanInterface += buildVrLanInterfacePartial(vrLanInterface)
546                         
547                          // dhcp
548                          def dhcp = getNodeXml(vrLan, "dhcp").drop(38).trim()
549                          def rebuildDhcp = buildDhcp(dhcp)
550                          rebuildVrLanInterface += rebuildDhcp
551                          
552                          // pat
553                          def pat = getNodeXml(vrLan, "pat").drop(38).trim()
554                          def rebuildPat = buildPat(pat)
555                          rebuildVrLanInterface += rebuildPat
556                          
557                          // nat
558                          def rebuildNat = ""
559                          try { // optional
560                                 def nat = getNodeXml(vrLan, "nat").drop(38).trim()
561                                 rebuildNat = buildNat(nat)
562                          } catch (Exception e) {
563                                  log("ERROR", " Optional - Exception 'nat' ")
564                          }
565                          rebuildVrLanInterface += rebuildNat
566                                                                                 
567                          // firewall-lite
568                          def firewallLite = getNodeXml(vrLan, "firewall-lite").drop(38).trim()
569                          def rebuildFirewallLite = buildFirewallLite(firewallLite)
570                          rebuildVrLanInterface += rebuildFirewallLite
571                          
572                          // static-routes
573                          def rebuildStaticRoutes = ""
574                          try { // optional 
575                                  def staticRoutes = getNodeXml(vrLan, "static-routes").drop(38).trim()
576                                  rebuildStaticRoutes = buildStaticRoutes(staticRoutes)
577                         } catch (Exception e) {
578                                  log("ERROR", " Optional - Exception 'static-routes' ")
579                         }
580                         rebuildVrLanInterface += rebuildStaticRoutes
581                          
582                    rebuildVrLan += rebuildVrLanInterface
583                    rebuildVrLan += "</tns2:vr-lan-interface>"
584                    rebuildVrLan += "</tns2:vr-lan>"
585                         
586                 }
587                 log("DEBUG", " rebuildVrLan - " + rebuildVrLan)
588                 return rebuildVrLan             
589         }
590         
591         // Build vr-lan-interface
592         def buildVrLanInterfacePartial(xmlInput) {
593                 def rebuildingVrLanInterface = ''
594                 if (xmlInput != null) {
595                         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"]
596                         rebuildingVrLanInterface += buildElements(xmlInput, vrLanInterfaceList, "")
597                         rebuildingVrLanInterface += "<tns2:v4-public-lan-prefixes>"
598                         try { // optional
599                                 def tProvidedV4LanPublicPrefixes = getNodeXml(xmlInput, "v4-public-lan-prefixes").drop(38).trim()
600                                 def tProvidedV4LanPublicPrefixesList = ["request-index", "v4-next-hop-address", "v4-lan-public-prefix", "v4-lan-public-prefix-length" ]
601                                 rebuildingVrLanInterface += buildElementsUnbounded(xmlInput, tProvidedV4LanPublicPrefixesList, "t-provided-v4-lan-public-prefixes")
602                         } catch (Exception ex) {
603                                 log("ERROR", " Optional - Exception VR-LAN INTERFACE 'v4-public-lan-prefixes' ")
604                         }
605                         rebuildingVrLanInterface += "</tns2:v4-public-lan-prefixes>"
606                         rebuildingVrLanInterface += "<tns2:v6-public-lan-prefixes>"
607                         try { // optional
608                                 def tProvidedV6LanPublicPrefixes = getNodeXml(xmlInput, "v6-public-lan-prefixes").drop(38).trim()
609                                 def tProvidedV6LanPublicPrefixesList = ["request-index", "v6-next-hop-address", "v6-lan-public-prefix", "v6-lan-public-prefix-length" ]
610                                 rebuildingVrLanInterface += buildElementsUnbounded(xmlInput, tProvidedV6LanPublicPrefixesList, "t-provided-v6-lan-public-prefixes")
611                         } catch (Exception e) {
612                                 log("ERROR", " Optional - Exception VR-LAN INTERFACE 'v6-public-lan-prefixes' ")
613                         }
614                         rebuildingVrLanInterface += "</tns2:v6-public-lan-prefixes>"
615                 }
616                 log("DEBUG", " rebuildingVrLanInterface - " + rebuildingVrLanInterface)
617                 return rebuildingVrLanInterface
618         }
619         
620         // Build dhcp
621         def buildDhcp(xmlInput) {
622                 def rebuildingDhcp = ''
623                 if (xmlInput != null) {
624                         def dhcpData = new XmlSlurper().parseText(xmlInput)
625                         rebuildingDhcp = "<tns2:dhcp>"
626                         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"]
627                         rebuildingDhcp += buildElements(xmlInput, dhcpList1, "")
628                         try { // optional
629                                 def excludedV4DhcpAddressesFromDefaultPoolList = ["excluded-v4-address"]
630                                 rebuildingDhcp += buildElementsUnbounded(xmlInput, excludedV4DhcpAddressesFromDefaultPoolList, "excluded-v4-dhcp-addresses-from-default-pool")
631                         } catch (Exception e) {
632                                 log("ERROR", " Optional - Exception DHCP 'excluded-v4-dhcp-addresses-from-default-pool' ")
633                         }
634                         try { // optional
635                                 def v4DhcpPools = dhcpData.'**'.findAll {it.name() == "v4-dhcp-pools"}
636                                 def v4DhcpPoolsSize = v4DhcpPools.size()
637                                 // println " v4DhcpPoolsSize = " + v4DhcpPools.size()
638                                 for (i in 0..v4DhcpPoolsSize-1) {
639                                         def v4DhcpPool = v4DhcpPools[i]
640                                         def v4DhcpPoolXml = XmlUtil.serialize(v4DhcpPool)
641                                         rebuildingDhcp += "<tns2:v4-dhcp-pools>"
642                                         def v4DhcpPoolsList1 = ["v4-dhcp-pool-prefix", "v4-dhcp-pool-prefix-length" ]
643                                         rebuildingDhcp += buildElements(v4DhcpPoolXml, v4DhcpPoolsList1, "")
644                                         try { // optional
645                                            def excludedV4AddressesList = ["excluded-v4-address"]
646                                            rebuildingDhcp += buildElementsUnbounded(v4DhcpPoolXml, excludedV4AddressesList, "excluded-v4-addresses")
647                                         } catch (Exception e) {
648                                            log("ERROR", " Optional - Exception DHCP 'excluded-v4-addresses' ")
649                                         }
650                                         def v4DhcpPoolsList2 = ["v4-dhcp-relay-gateway-address", "v4-dhcp-relay-next-hop-address"]
651                                         rebuildingDhcp += buildElements(v4DhcpPoolXml, v4DhcpPoolsList2, "")
652                                         rebuildingDhcp += "</tns2:v4-dhcp-pools>"
653                                  }
654                          } catch (Exception e) {
655                                   log("ERROR"," Optional - Exception DHCP 'v4-dhcp-pools' ")
656                          }
657                          def dhcpList2 = ["use-v6-default-pool", "v6-dhcp-default-pool-prefix", "v6-dhcp-default-pool-prefix-length"]
658                          rebuildingDhcp += buildElements(xmlInput, dhcpList2, "")
659                          try { // optional
660                                  def excludedV6DhcpAddressesFromDdefaultPoolList = ["excluded-v6-address"]
661                                  rebuildingDhcp += buildElementsUnbounded(xmlInput, excludedV6DhcpAddressesFromDdefaultPoolList, "excluded-v6-dhcp-addresses-from-default-pool")
662                          } catch (Exception e) {
663                            log("ERROR", " Optional - Exception DHCP 'excluded-v6-dhcp-addresses-from-default-pool' ")
664                          }
665                          try { // optional
666                                  def v6DhcpPools = dhcpData.'**'.findAll {it.name() == "v6-dhcp-pools"}
667                                  def v6DhcpPoolsSize = v6DhcpPools.size()
668                                  //println " v6DhcpPoolsSize = " + v6DhcpPools.size()
669                                  for (i in 0..v6DhcpPoolsSize-1) {
670                                         def v6DhcpPool = v6DhcpPools[i]
671                                         def v6DhcpPoolXml = XmlUtil.serialize(v6DhcpPool)
672                                         rebuildingDhcp += "<tns2:v6-dhcp-pools>"
673                                         def v6DhcpPoolsList1 = ["v6-dhcp-pool-prefix", "v6-dhcp-pool-prefix-length"]
674                                         rebuildingDhcp += buildElements(v6DhcpPoolXml, v6DhcpPoolsList1, "")
675                                         try { // optional
676                                                 def excludedV6AddressesList = ["excluded-v6-address"]
677                                                 rebuildingDhcp += buildElementsUnbounded(v6DhcpPoolXml, excludedV6AddressesList, "excluded-v6-addresses")
678                                         } catch (Exception e) {
679                                                          log("ERROR", " Optional - Exception DHCP 'excluded-v6-addresses' ")
680                                         }
681                                         def v6DhcpPoolsList2 = ["v6-dhcp-relay-gateway-address", "v6-dhcp-relay-next-hop-address"]
682                                         rebuildingDhcp += buildElements(v6DhcpPoolXml, v6DhcpPoolsList2, "")
683                                         rebuildingDhcp += "</tns2:v6-dhcp-pools>"
684                                  }
685                          } catch (Exception e) {
686                                  log("ERROR", " Optional - Exception DHCP 'v6-dhcp-pools' ")
687                          }
688                          rebuildingDhcp += "</tns2:dhcp>"
689                 }        
690                 log("DEBUG", " rebuildingDhcp - " + rebuildingDhcp)
691                 return rebuildingDhcp
692         }       
693
694         // Build pat
695         def buildPat(xmlInput) {
696                  def rebuildingPat = ''
697                  if (xmlInput != null) {
698                          rebuildingPat = "<tns2:pat>"
699                          def patList = ["v4-pat-enabled", "use-v4-default-pool", "v4-pat-default-pool-prefix", "v4-pat-default-pool-prefix-length"]
700                          rebuildingPat += buildElements(xmlInput, patList, "")
701                          try { // optional
702                                  def v4PatPools = getNodeXml(xmlInput, "v4-pat-pools").drop(38).trim()
703                                  def v4PatPoolsList = ["v4-pat-pool-prefix", "v4-pat-pool-prefix-length", "v4-pat-pool-next-hop-address"]
704                                  rebuildingPat += buildElementsUnbounded(xmlInput, v4PatPoolsList, "v4-pat-pools")
705                          } catch (Exception e) {
706                                 log("ERROR", " Optional - Exception 'v4-pat-pool-next-hop-address' ")
707                          }
708                          rebuildingPat += "</tns2:pat>"
709                  }
710                  log("DEBUG", " rebuildingPat - " + rebuildingPat)
711              return rebuildingPat
712     }
713         
714         // Build nat
715         def buildNat(xmlInput) {
716                 def rebuildingNat = ''
717                 if (xmlInput != null) {
718                         rebuildingNat = "<tns2:nat>"
719                         rebuildingNat += buildElements(xmlInput, ["v4-nat-enabled"], "")
720                         try { // optional
721                          def v4NatMappingEntries = getNodeXml(xmlInput, "v4-nat-mapping-entries").drop(38).trim()
722                          def v4NatMappingEntriesList = ["v4-nat-internal", "v4-nat-next-hop-address", "v4-nat-external"]
723                          rebuildingNat += buildElementsUnbounded(xmlInput, v4NatMappingEntriesList, "v4-nat-mapping-entries")
724                         } catch (Exception e) {
725                            log("ERROR", " Optional - Exception 'v4-nat-external' ")
726                         }
727                         rebuildingNat += "</tns2:nat>"
728                 }
729                 log("DEBUG", " rebuildingNat - " + rebuildingNat)
730             return rebuildingNat
731         }                               
732         
733         // Build firewall-lite
734         def buildFirewallLite(xmlInput) {
735                 def rebuildingFirewallLite = ''
736                 
737                 if (xmlInput != null) {
738                         
739                         def firewallLiteData = new XmlSlurper().parseText(xmlInput)
740                         rebuildingFirewallLite = "<tns2:firewall-lite>"
741                         def firewallLiteList = ["stateful-firewall-lite-v4-enabled", "stateful-firewall-lite-v6-enabled"]
742                         rebuildingFirewallLite += buildElements(xmlInput, firewallLiteList, "")
743                         
744                          try { // optional
745                                  def v4FirewallPacketFilters = firewallLiteData.'**'.findAll {it.name() == "v4-firewall-packet-filters"}
746                                  def v4FirewallPacketFiltersSize = v4FirewallPacketFilters.size()
747                                  //println " v4FirewallPacketFiltersSize = " + v4FirewallPacketFilters.size()
748                                  for (i in 0..v4FirewallPacketFiltersSize-1) {
749                                def v4FirewallPacketFilter = v4FirewallPacketFilters[i]
750                                def v4FirewallPacketFilterXml = XmlUtil.serialize(v4FirewallPacketFilter)
751                                    rebuildingFirewallLite += "<tns2:v4-firewall-packet-filters>"
752                                    def v4FirewallPacketFiltersList = ["v4-firewall-prefix", "v4-firewall-prefix-length", "allow-icmp-ping"]
753                                    rebuildingFirewallLite += buildElements(v4FirewallPacketFilterXml, v4FirewallPacketFiltersList, "")
754                                    try {  // optional
755                                   def udpPortsList = ["port-number"]
756                                           rebuildingFirewallLite += buildElementsUnbounded(v4FirewallPacketFilterXml, udpPortsList, "udp-ports")
757                                    } catch (Exception e) {
758                                           log("ERROR", " Optional - Exception FIREWALL-LITE v4 'udp-ports' ")
759                                    }
760                                    try {  // optional
761                                           def tcpPortsList =  ["port-number"]
762                                           rebuildingFirewallLite += buildElementsUnbounded(v4FirewallPacketFilterXml, tcpPortsList, "tcp-ports")
763                                    } catch (Exception e) {
764                                       log("ERROR", " Optional - Exception FIREWALL-LITE v4 'tcp-ports' ")
765                                    }
766                                    rebuildingFirewallLite += "</tns2:v4-firewall-packet-filters>"
767                                  }
768                          } catch (Exception e) {
769                                  log("ERROR", " Optional - Exception FIREWALL-LITE 'v4-firewall-packet-filters' ")
770                          }
771                          
772                          try { // optional
773                                  def v6FirewallPacketFilters = firewallLiteData.'**'.findAll {it.name() == "v6-firewall-packet-filters"}
774                                  def v6FirewallPacketFiltersSize = v6FirewallPacketFilters.size()
775                                  //println " v6FirewallPacketFiltersSize = " + v6FirewallPacketFilters.size()
776                                  for (i in 0..v6FirewallPacketFiltersSize-1) {
777                                         def v6FirewallPacketFilter = v6FirewallPacketFilters[i]
778                                         def v6FirewallPacketFilterXml = XmlUtil.serialize(v6FirewallPacketFilter)
779                                         rebuildingFirewallLite += "<tns2:v6-firewall-packet-filters>"
780                                         def v6FirewallPacketFiltersList = ["v6-firewall-prefix", "v6-firewall-prefix-length", "allow-icmp-ping"]
781                                         rebuildingFirewallLite += buildElements(v6FirewallPacketFilterXml, v6FirewallPacketFiltersList, "")
782                                         try { // optional
783                                                 def udpPortsList = ["port-number"]
784                                                 rebuildingFirewallLite += buildElementsUnbounded(v6FirewallPacketFilterXml, udpPortsList, "udp-ports")
785                                         } catch (Exception e) {
786                                       log("ERROR", " Optional - Exception FIREWALL-LITE v6 'udp-ports' ")
787                                         }
788                                         try { // optional
789                                                 def tcpPortsList =  ["port-number"]
790                                                 rebuildingFirewallLite += buildElementsUnbounded(v6FirewallPacketFilterXml, tcpPortsList, "tcp-ports")
791                                         } catch (Exception e) {
792                                         log("ERROR", " Optional - Exception FIREWALL-LITE v6 'tcp-ports' ")
793                                         }
794                                rebuildingFirewallLite += "</tns2:v6-firewall-packet-filters>"
795                                  }
796                          } catch (Exception e) {
797                                  log("ERROR", " Optional - Exception FIREWALL-LITE 'v6-firewall-packet-filters' ")
798                          }
799                          rebuildingFirewallLite+= "</tns2:firewall-lite>"
800                 }
801                 log("DEBUG", " rebuildingFirewallLite - " + rebuildingFirewallLite)
802                 return rebuildingFirewallLite
803      }
804         
805         def buildStaticRoutes(xmlInput) {
806                 def rebuildingStaticRoutes = ''
807                 if (xmlInput != null) {
808                         rebuildingStaticRoutes = "<tns2:static-routes>"
809                         def v4StaticRouteslist = ["v4-static-route-prefix","v4-static-route-prefix-length", "v4-next-hop-address"]
810                         rebuildingStaticRoutes += buildElementsUnbounded(xmlInput, v4StaticRouteslist, "v4-static-routes")
811                         def v6StaticRouteslist = ["v6-static-route-prefix","v6-static-route-prefix-length", "v6-next-hop-address"]
812                         rebuildingStaticRoutes += buildElementsUnbounded(xmlInput, v6StaticRouteslist, "v6-static-routes")
813                         rebuildingStaticRoutes += "</tns2:static-routes>"
814                 }
815                 log("DEBUG", " rebuildingStaticRoutes - " + rebuildingStaticRoutes)
816                 return rebuildingStaticRoutes
817         }
818         
819         public String generateCurrentTimeInUtc(){
820                 final  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
821                 sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
822                 final String utcTime = sdf.format(new Date());
823                 return utcTime;
824         }
825         
826         public String generateCurrentTimeInGMT(){
827                 final  SimpleDateFormat sdf = new SimpleDateFormat("E, d MMM yyyy h:m:s z");
828                 sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
829                 final String utcTime = sdf.format(new Date());
830                 return utcTime;
831         }
832         
833
834         /**
835          * @param encryptedAuth: encrypted credentials from urn properties
836          * @param msoKey: key to use to decrypt from urn properties
837          * @return base 64 encoded basic auth credentials
838          */
839         def getBasicAuth(encryptedAuth, msoKey){
840                 if ((encryptedAuth == null || encryptedAuth.isEmpty()) || (msoKey == null || msoKey.isEmpty()))
841                         return null
842                 try {
843                         def auth = decrypt(encryptedAuth, msoKey)
844                         byte[] encoded = Base64.encodeBase64(auth.getBytes())
845                         String encodedString = new String(encoded)
846                         encodedString = "Basic " + encodedString
847                         return encodedString
848                 } catch (Exception ex) {
849                         log("ERROR", "Unable to encode basic auth")
850                         throw ex
851                 }
852         }
853         
854         def encrypt(toEncrypt, msokey){
855                 try {
856                         String result = CryptoUtils.encrypt(toEncrypt, msokey);
857                         return result
858                 }
859                 catch (Exception e) {
860                         log("ERROR", "Failed to encrypt credentials")
861                 }
862         }
863         
864         def decrypt(toDecrypt, msokey){
865                 try {
866                         String result = CryptoUtils.decrypt(toDecrypt, msokey);
867                         return result
868                 }
869                 catch (Exception e) {
870                         log("ERROR", "Failed to decrypt credentials")
871                         throw e
872                 }
873         }
874         
875         /**
876          * Return URL with qualified host name (if any) or urn mapping
877          * @param  String url from urn mapping
878          * @return String url with qualified host name
879          */
880         public String getQualifiedHostNameForCallback(String urnCallbackUrl) {
881                 def callbackUrlToUse = urnCallbackUrl
882                 try{
883                         //swap host name with qualified host name from the jboss properties
884                         def qualifiedHostName = System.getProperty("jboss.qualified.host.name")
885                         if(qualifiedHostName!=null){
886                                 log("DEBUG", "qualifiedHostName:\n" + qualifiedHostName)
887                                 callbackUrlToUse = callbackUrlToUse.replaceAll("(http://)(.*)(:28080*)", {orig, first, torepl, last -> "${first}${qualifiedHostName}${last}"})
888                         }
889                 }catch(Exception e){
890                                 log("DEBUG", "unable to grab qualified host name, using what's in urn properties for callbackurl. Exception was: " + e.printStackTrace())
891                 }
892                 return callbackUrlToUse
893                 
894         }
895         
896         /**
897          * Retrieves text context of the element if the element exists, returns empty string otherwise
898          * @param com.sun.org.apache.xerces.internal.dom.DeferredElementNSImpl element to parse
899          * param String tagName tagName
900          * @return String text content of the element
901          */
902          public String getElementText(Element element, String tagName) {
903                 String text = ""
904                 org.w3c.dom.NodeList nodeList = element.getElementsByTagNameNS("*", tagName)
905                 if (nodeList != null && nodeList.length > 0) {
906                         text = nodeList.item(0).getTextContent()
907                 }
908                 return text
909          }
910          
911          /**
912           *
913           * Find the lowest unused module-index value in a given xml
914           */
915          public String getLowestUnusedIndex(String xml) {
916                  if (xml == null || xml.isEmpty()) {
917                          return "0"
918                  }               
919                  def moduleIndexList = getMultNodes(xml, "module-index") 
920                  if (moduleIndexList == null || moduleIndexList.size() == 0) {                  
921                          return "0"
922                  }
923                  
924                  def sortedModuleIndexList = moduleIndexList.sort{ a, b -> a as Integer <=> b as Integer}
925                 
926                  for (i in 0..sortedModuleIndexList.size()-1) {
927                          if (Integer.parseInt(sortedModuleIndexList[i]) != i) {
928                                  return i.toString()
929                          }
930                  }
931                  return sortedModuleIndexList.size().toString()
932          }
933         /**
934          * This utility checks if there is transaction id already present in MDC.
935          * If found, it returns same else creates new, sets in MDC for future use before returning
936          * @return String RequestId in UUID format.
937          */
938         public String getRequestID()
939         {
940                 String requestId = MDC.get("RequestId")
941                 if(requestId == null || requestId.isEmpty())
942                 {
943                         requestId = java.util.UUID.randomUUID()
944                         MDC.put("RequestId",requestId)
945                         log("DEBUG","MsoUtils - Created new RequestId: " + requestId)
946                 }
947                 else
948                 {
949                         log("DEBUG","MsoUtils - Using existing RequestId: " + requestId)
950                 }
951
952                 return requestId
953         }
954
955         /**
956          * Remove all the empty nodes and attributes from the within the given node
957          * @param node
958          * @return true if all empty nodes and attributes were removed.
959          */
960         public boolean cleanNode( Node node ) {
961                 node.attributes().with { a ->
962                         a.findAll { !it.value }.each { a.remove( it.key ) }
963                 }
964                 node.children().with { kids ->
965                         kids.findAll { it instanceof Node ? !cleanNode( it ) : false }
966                                         .each { kids.remove( it ) }
967                 }
968                 node.attributes() || node.children() || node.text()
969         }
970
971         /**
972          *
973          * @param xml
974          * @return String representation of xml after removing the empty nodes and attributes
975          */
976         public String cleanNode(String xmlString) {
977                 def xml = new XmlParser(false, false).parseText(xmlString)
978                 cleanNode(xml)
979                 return XmlUtil.serialize(xml)
980         }
981 }