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