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