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