Springboot 2.0 upgrade
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / onap / so / bpmn / common / scripts / AaiUtil.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 import java.util.regex.Matcher
23 import java.util.regex.Pattern
24
25 import javax.ws.rs.core.UriBuilder
26
27 import org.camunda.bpm.engine.delegate.BpmnError
28 import org.camunda.bpm.engine.delegate.DelegateExecution
29 import org.onap.aai.domain.yang.GenericVnf
30 import org.onap.so.bpmn.core.UrnPropertiesReader;
31 import org.onap.so.client.aai.AAIVersion
32 import org.onap.so.client.aai.entities.uri.AAIUri
33 import org.onap.so.logger.MessageEnum
34 import org.onap.so.logger.MsoLogger
35 import org.onap.so.openpojo.rules.HasToStringRule
36 import org.onap.so.rest.APIResponse;
37 import org.onap.so.rest.RESTClient
38 import org.onap.so.rest.RESTConfig
39
40 @Deprecated
41 class AaiUtil {
42         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, AaiUtil.class);
43
44
45         public MsoUtils utils = new MsoUtils()
46         public static final String AAI_NAMESPACE_STRING_KEY = 'mso.workflow.global.default.aai.namespace'
47         public static final String DEFAULT_VERSION_KEY = 'mso.workflow.global.default.aai.version'
48
49         private String aaiNamespace = null;
50
51         private AbstractServiceTaskProcessor taskProcessor
52
53         public AaiUtil(AbstractServiceTaskProcessor taskProcessor) {
54                 this.taskProcessor = taskProcessor
55         }
56
57         public String getBusinessSPPartnerUri(DelegateExecution execution) {
58                 def uri = getUri(execution, 'sp-partner')
59                 msoLogger.debug('AaiUtil.getBusinessSPPartnerUri() - AAI URI: ' + uri)
60                 return uri
61         }
62
63         public String getVersion(DelegateExecution execution, resourceName, processKey) {
64                 def versionWithResourceKey = "mso.workflow.default.aai.${resourceName}.version"
65                 def versionWithProcessKey = "mso.workflow.custom.${processKey}.aai.version"
66
67                 def version = UrnPropertiesReader.getVariable(versionWithProcessKey, execution)
68                 if (version) {
69                         msoLogger.debug("AaiUtil.getVersion() - using flow specific ${versionWithProcessKey}=${version}")
70                         return version
71                 }
72
73                 version = UrnPropertiesReader.getVariable(versionWithResourceKey, execution)
74                 if (version) {
75                         msoLogger.debug("AaiUtil.getVersion() - using resource specific ${versionWithResourceKey}=${version}")
76                         return version
77                 }
78
79                 version = UrnPropertiesReader.getVariable(DEFAULT_VERSION_KEY, execution)
80                 if (version) {
81                         msoLogger.debug("AaiUtil.getVersion() - using default version ${DEFAULT_VERSION_KEY}=${version}")
82                         return version
83                 }
84
85                 (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, "Internal Error: One of the following should be defined in MSO URN properties file: ${versionWithResourceKey}, ${versionWithProcessKey}, ${DEFAULT_VERSION_KEY}")
86         }
87
88         public String createAaiUri(AAIUri uri) {
89                 return createAaiUri(AAIVersion.valueOf('V' + UrnPropertiesReader.getVariable(DEFAULT_VERSION_KEY)), uri)
90         }
91         public String createAaiUri(AAIVersion version, AAIUri uri) {
92                 String endpoint = UrnPropertiesReader.getVariable("aai.endpoint")
93                 String result = UriBuilder.fromUri(endpoint).path('aai').path(version.toString()).build().toString()
94                 return UriBuilder.fromUri(result + uri.build().toString()).build().toString()
95         }
96
97         public String setNamespace(DelegateExecution execution) {
98                 def key = AAI_NAMESPACE_STRING_KEY
99                 aaiNamespace = UrnPropertiesReader.getVariable(key, execution)
100                 if (aaiNamespace == null ) {
101                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, 'Internal Error: AAI URI entry for ' + key + ' not defined in the MSO URN properties file')
102                 }
103         }
104
105         public String getNamespace() {
106                 return getNamespace(AAIVersion.valueOf('V' + UrnPropertiesReader.getVariable(DEFAULT_VERSION_KEY)))
107         }
108
109         public String getNamespace(AAIVersion version) {
110                 String namespace = UrnPropertiesReader.getVariable(AAI_NAMESPACE_STRING_KEY)
111                 if (namespace == null) {
112                    throw new Exception('Internal Error: AAI Namespace has not been set yet. A getUri() method needs to be invoked first.')
113                 }
114
115                 return namespace + version
116         }
117         /**
118          * This method can be used for getting the building namespace out of uri.
119          *  NOTE: A getUri() method needs to be invoked first.
120          *        Alternative method is the getNamespaceFromUri(DelegateExecution execution, String uri)
121          * return namespace (plus version from uri)
122          *
123          * @param url
124          *
125          * @return namespace
126          */
127         public String getNamespaceFromUri(String uri) {
128                 String namespace = UrnPropertiesReader.getVariable(AAI_NAMESPACE_STRING_KEY)
129                  if (namespace == null) {
130                         throw new Exception('Internal Error: AAI Namespace has not been set yet. A getUri() method needs to be invoked first.')
131                 }
132                 if(uri!=null){
133                         String version = getVersionFromUri(uri)
134                         return namespace + "v"+version
135                 }else{
136                         return namespace
137                 }
138         }
139
140         /**
141          * This method can be used for building namespace with aai version out of uri.
142          *   NOTE: 2 arguments: DelegateExecution execution & String uri
143          * @param execution
144          * @param url
145          *
146          * @return namespace
147          */
148         public String getNamespaceFromUri(DelegateExecution execution, String uri) {
149            String namespace = UrnPropertiesReader.getVariable(AAI_NAMESPACE_STRING_KEY, execution)
150            if (namespace == null ) {
151                    (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, 'Internal Error: AAI URI entry for ' + AAI_NAMESPACE_STRING_KEY + ' not defined in the MSO URN properties file')
152            }
153            if(uri!=null){
154                    String version = getVersionFromUri(uri)
155                    return namespace + "v"+version
156            }else{
157                    return namespace
158            }
159    }
160
161         /**
162          * This is used to extract the version from uri.
163          *
164          * @param uri
165          *
166          * @return version
167          */
168         private String getVersionFromUri(String uri) {
169
170                 Matcher versionRegEx = Pattern.compile("/v(\\d+)").matcher(uri)
171                 if (versionRegEx.find()) {
172                         return versionRegEx.group(1);
173                 }
174
175                 return "";
176         }
177
178
179         /**
180          * This reusable method can be used for making AAI Get Calls. The url should
181          * be passed as a parameter along with the execution.  The method will
182          * return an APIResponse.
183          *
184          * @param execution
185          * @param url
186          *
187          * @return APIResponse
188          *
189          */
190         public APIResponse executeAAIGetCall(DelegateExecution execution, String url){
191                 msoLogger.trace("STARTED Execute AAI Get Process ")
192                 APIResponse apiResponse = null
193                 try{
194                         String uuid = utils.getRequestID()
195                         msoLogger.debug("Generated uuid is: " + uuid)
196                         msoLogger.debug("URL to be used is: " + url)
197
198                         String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
199
200                         RESTConfig config = new RESTConfig(url);
201                         RESTClient client = new RESTClient(config).addHeader("X-FromAppId", "MSO").addHeader("X-TransactionId", uuid).addHeader("Accept","application/xml");
202
203                         if (basicAuthCred != null && !"".equals(basicAuthCred)) {
204                                 client.addAuthorizationHeader(basicAuthCred)
205                         }
206                         apiResponse = client.httpGet()
207
208                         msoLogger.trace("COMPLETED Execute AAI Get Process ")
209                 }catch(Exception e){
210                         msoLogger.debug("Exception occured while executing AAI Get Call. Exception is: \n" + e)
211                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, e.getMessage())
212                 }
213                 return apiResponse
214         }
215
216
217         /**
218          * This reusable method can be used for making AAI httpPut Calls. The url should
219          * be passed as a parameter along with the execution and payload.  The method will
220          * return an APIResponse.
221          *
222          * @param execution
223          * @param url
224          * @param payload
225          *
226          * @return APIResponse
227          *
228          */
229         public APIResponse executeAAIPutCall(DelegateExecution execution, String url, String payload){
230                 msoLogger.trace("Started Execute AAI Put Process ")
231                 APIResponse apiResponse = null
232                 try{
233                         String uuid = utils.getRequestID()
234                         msoLogger.debug("Generated uuid is: " + uuid)
235                         msoLogger.debug("URL to be used is: " + url)
236
237                         String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
238
239                         RESTConfig config = new RESTConfig(url);
240                         RESTClient client = new RESTClient(config).addHeader("X-FromAppId", "MSO").addHeader("X-TransactionId", uuid).addHeader("Content-Type", "application/xml").addHeader("Accept","application/xml");
241                         if (basicAuthCred != null && !"".equals(basicAuthCred)) {
242                                 client.addAuthorizationHeader(basicAuthCred)
243                         }
244                         apiResponse = client.httpPut(payload)
245
246                         msoLogger.trace("Completed Execute AAI Put Process ")
247                 }catch(Exception e){
248                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Exception occured while executing AAI Put Call.", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, e);
249                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, e.getMessage())
250                 }
251                 return apiResponse
252         }
253
254         /**
255          * This reusable method can be used for making AAI httpPatch Calls. The url should
256          * be passed as a parameter along with the execution and payload.  The method will
257          * return an APIResponse.
258          *
259          * @param execution
260          * @param url
261          * @param payload
262          *
263          * @return APIResponse
264          *
265          */
266         public APIResponse executeAAIPatchCall(DelegateExecution execution, String url, String payload){
267                 msoLogger.trace("Started Execute AAI Patch Process ")
268                 APIResponse apiResponse = null
269                 try{
270                         String uuid = utils.getRequestID()
271                         msoLogger.debug("Generated uuid is: " + uuid)
272
273                         msoLogger.debug("URL to be used is: " + url)
274
275                         String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
276
277                         RESTConfig config = new RESTConfig(url);
278                         RESTClient client = new RESTClient(config).addHeader("X-FromAppId", "MSO").addHeader("X-TransactionId", uuid).addHeader("Content-Type", "application/merge-patch+json").addHeader("Accept","application/json");
279                         if (basicAuthCred != null && !"".equals(basicAuthCred)) {
280                                 client.addAuthorizationHeader(basicAuthCred)
281                         }
282                         apiResponse = client.httpPatch(payload)
283
284                         msoLogger.trace("Completed Execute AAI Patch Process ")
285                 }catch(Exception e){
286                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Exception occured while executing AAI Patch Call.", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, e);
287                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, e.getMessage())
288                 }
289                 return apiResponse
290         }
291
292
293         /**
294          * This reusable method can be used for making AAI Delete Calls. The url should
295          * be passed as a parameter along with the execution.  The method will
296          * return an APIResponse.
297          *
298          * @param execution
299          * @param url
300          *
301          * @return APIResponse
302          *
303          */
304         public APIResponse executeAAIDeleteCall(DelegateExecution execution, String url){
305                 msoLogger.trace("Started Execute AAI Delete Process ")
306                 APIResponse apiResponse = null
307                 try{
308                         String uuid = utils.getRequestID()
309                         msoLogger.debug("Generated uuid is: " + uuid)
310                         msoLogger.debug("URL to be used is: " + url)
311
312                         String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
313
314                         RESTConfig config = new RESTConfig(url);
315                         RESTClient client = new RESTClient(config).addHeader("X-FromAppId", "MSO").addHeader("X-TransactionId", uuid).addHeader("Accept","application/xml");
316                         if (basicAuthCred != null && !"".equals(basicAuthCred)) {
317                                 client.addAuthorizationHeader(basicAuthCred)
318                         }
319                         apiResponse = client.delete()
320
321                         msoLogger.trace("Completed Execute AAI Delete Process ")
322                 }catch(Exception e){
323                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Exception occured while executing AAI Delete Call.", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, e);
324                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, e.getMessage())
325                 }
326                 return apiResponse
327         }
328
329         /**
330          * This reusable method can be used for making AAI Delete Calls. The url should
331          * be passed as a parameter along with the execution.  The method will
332          * return an APIResponse.
333          *
334          * @param execution
335          * @param url
336          * @param payload
337          *
338          * @return APIResponse
339          *
340          */
341         public APIResponse executeAAIDeleteCall(DelegateExecution execution, String url, String payload, String authHeader){
342                 msoLogger.trace("Started Execute AAI Delete Process ")
343                 APIResponse apiResponse = null
344                 try{
345                         String uuid = utils.getRequestID()
346                         msoLogger.debug("Generated uuid is: " + uuid)
347
348                         msoLogger.debug("URL to be used is: " + url)
349
350                         String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
351                         RESTConfig config = new RESTConfig(url);
352                         RESTClient client = new RESTClient(config).addHeader("X-FromAppId", "MSO").addHeader("X-TransactionId", uuid).addHeader("Accept","application/xml").addAuthorizationHeader(authHeader);
353                         if (basicAuthCred != null && !"".equals(basicAuthCred)) {
354                                 client.addAuthorizationHeader(basicAuthCred)
355                         }
356                         apiResponse = client.httpDelete(payload)
357
358                         msoLogger.trace("Completed Execute AAI Delete Process ")
359                 }catch(Exception e){
360                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Exception occured while executing AAI Delete Call.", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, e);
361                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, e.getMessage())
362                 }
363                 return apiResponse
364         }
365
366         /**
367          * This reusable method can be used for making AAI Post Calls. The url
368          * and payload should be passed as a parameters along with the execution.
369          * The method will return an APIResponse.
370          *
371          * @param execution
372          * @param url
373          * @param payload
374          *
375          * @return APIResponse
376          *
377          */
378         public APIResponse executeAAIPostCall(DelegateExecution execution, String url, String payload){
379                 msoLogger.trace("Started Execute AAI Post Process ")
380                 APIResponse apiResponse = null
381                 try{
382                         String uuid = utils.getRequestID()
383                         msoLogger.debug("Generated uuid is: " + uuid)
384                         msoLogger.debug("URL to be used is: " + url)
385
386                         String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
387                         RESTConfig config = new RESTConfig(url);
388                         RESTClient client = new RESTClient(config).addHeader("X-FromAppId", "MSO").addHeader("X-TransactionId", uuid).addHeader("Accept","application/xml");
389
390                         if (basicAuthCred != null && !"".equals(basicAuthCred)) {
391                                 client.addAuthorizationHeader(basicAuthCred)
392                         }
393                         apiResponse = client.httpPost(payload)
394
395                         msoLogger.trace("Completed Execute AAI Post Process ")
396                 }catch(Exception e){
397                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Exception occured while executing AAI Post Call.", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, e);
398                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, e.getMessage())
399                 }
400                 return apiResponse
401         }
402
403         /**
404          * This reusable method can be used for making AAI Post Calls. The url
405          * and payload should be passed as a parameters along with the execution.
406          * The method will return an APIResponse.
407          *
408          * @param execution
409          * @param url
410          * @param payload
411          * @param authenticationHeader - addAuthenticationHeader value
412          * @param headerName - name of header you want to add, i.e. addHeader(headerName, headerValue)
413          * @param headerValue - the header's value, i.e. addHeader(headerName, headerValue)
414          *
415          * @return APIResponse
416          *
417          */
418         public APIResponse executeAAIPostCall(DelegateExecution execution, String url, String payload, String authenticationHeaderValue, String headerName, String headerValue){
419                 msoLogger.trace("Started Execute AAI Post Process ")
420                 APIResponse apiResponse = null
421                 try{
422                         msoLogger.debug("URL to be used is: " + url)
423
424                         String basicAuthCred = utils.getBasicAuth(UrnPropertiesReader.getVariable("aai.auth", execution),UrnPropertiesReader.getVariable("mso.msoKey", execution))
425
426                         RESTConfig config = new RESTConfig(url);
427                         RESTClient client = new RESTClient(config).addAuthorizationHeader(authenticationHeaderValue).addHeader(headerName, headerValue)
428                         if (basicAuthCred != null && !"".equals(basicAuthCred)) {
429                                 client.addAuthorizationHeader(basicAuthCred)
430                         }
431                         apiResponse = client.httpPost(payload)
432
433                         msoLogger.trace("Completed Execute AAI Post Process ")
434                 }catch(Exception e){
435                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Exception occured while executing AAI Post Call.", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, e);
436                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, e.getMessage())
437                 }
438                 return apiResponse
439         }
440
441
442         /* Utility to get the Cloud Region from AAI
443          * Returns String cloud region id, (ie, cloud-region-id)
444          * @param execution
445          * @param url  - url for AAI get cloud region
446          * @param backend - "PO" - real region, or "SDNC" - v2.5 (fake region).
447          */
448
449         public String getAAICloudReqion(DelegateExecution execution, String url, String backend, inputCloudRegion){
450                 String regionId = ""
451                 try{
452                         APIResponse apiResponse = executeAAIGetCall(execution, url)
453                         String returnCode = apiResponse.getStatusCode()
454                         String aaiResponseAsString = apiResponse.getResponseBodyAsString()
455                         msoLogger.debug("Call AAI Cloud Region Return code: " + returnCode)
456                         execution.setVariable(execution.getVariable("prefix")+"queryCloudRegionReturnCode", returnCode)
457
458                         if(returnCode == "200"){
459                                 msoLogger.debug("Call AAI Cloud Region is Successful.")
460
461                                 String regionVersion = taskProcessor.utils.getNodeText(aaiResponseAsString, "cloud-region-version")
462                                 msoLogger.debug("Cloud Region Version from AAI for " + backend + " is: " + regionVersion)
463                                 if (backend == "PO") {
464                                         regionId = taskProcessor.utils.getNodeText(aaiResponseAsString, "cloud-region-id")
465                                 } else { // backend not "PO"
466                                         if (regionVersion == "2.5" ) {
467                                                 regionId = "AAIAIC25"
468                                         } else {
469                                                 regionId = taskProcessor.utils.getNodeText(aaiResponseAsString, "cloud-region-id")
470                                         }
471                                 }
472                                 if(regionId == null){
473                                         throw new BpmnError("MSOWorkflowException")
474                                 }
475                                 msoLogger.debug("Cloud Region Id from AAI " + backend + " is: " + regionId)
476                         }else if (returnCode == "404"){ // not 200
477                                 if (backend == "PO") {
478                                         regionId = inputCloudRegion
479                                 }else{  // backend not "PO"
480                                         regionId = "AAIAIC25"
481                                 }
482                                 msoLogger.debug("Cloud Region value for code='404' of " + backend + " is: " + regionId)
483                         }else{
484                                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Call AAI Cloud Region is NOT Successful.", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "");
485                                 throw new BpmnError("MSOWorkflowException")
486                         }
487                 }catch(Exception e) {
488                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Exception occured while getting the Cloud Reqion.", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, e.getMessage());
489                         (new ExceptionUtil()).buildAndThrowWorkflowException(execution, 9999, e.getMessage())
490                 }
491                 return regionId
492         }
493
494         /* returns xml Node with service-type of searchValue */
495         def searchServiceType(xmlInput, searchValue){
496                 def fxml= new XmlSlurper().parseText(xmlInput)
497                 def ret = fxml.'**'.find {it.'service-type' == searchValue}
498                 return ret
499         }
500
501         /* returns xml Node with service-instance-id of searchValue */
502         def searchServiceInstanceId(xmlInput, searchValue){
503                 def ret = xmlInput.'**'.find {it.'service-instance-id' == searchValue}
504                 return ret
505         }
506
507         /**
508          * Get the lowest unused VF Module index from AAI response for a given module type. The criteria for
509          * determining module type is specified by "key" parameter (for example, "persona-model-id"),
510          * the value for filtering is specified in "value" parameter
511          *
512          * @param execution
513          * @param aaiVnfResponse
514          * @param key
515          * @param value
516          *
517          * @return moduleIndex
518          *
519          */
520         public int getLowestUnusedVfModuleIndexFromAAIVnfResponse(DelegateExecution execution, GenericVnf aaiVnfResponse, String key, String value) {
521                 if (aaiVnfResponse != null) {
522                         String vfModulesText = taskProcessor.utils.getNodeXml(aaiVnfResponse, "vf-modules")
523                         if (aaiVnfResponse.getVfModules() == null || aaiVnfResponse.getVfModules().getVfModule().isEmpty()) {
524                                 msoLogger.debug("There are no VF modules in this VNF yet")
525                                 return 0
526                         }
527                         else {
528                                 def xmlVfModules= new XmlSlurper().parseText(vfModulesText)
529                                 def vfModules = xmlVfModules.'**'.findAll {it.name() == "vf-module"}
530                                 int vfModulesSize = 0
531                                 if (vfModules != null) {
532                                         vfModulesSize = vfModules.size()
533                                 }
534                                 String matchingVfModules = "<vfModules>"
535                                 for (i in 0..vfModulesSize-1) {
536                                         def vfModuleXml = groovy.xml.XmlUtil.serialize(vfModules[i])
537                                         def keyFromAAI = taskProcessor.utils.getNodeText(vfModuleXml, key)
538                                         if (keyFromAAI != null && keyFromAAI.equals(value)) {
539                                                 matchingVfModules = matchingVfModules + taskProcessor.utils.removeXmlPreamble(vfModuleXml)
540                                         }
541                                 }
542                                 matchingVfModules = matchingVfModules + "</vfModules>"
543                                 msoLogger.debug("Matching VF Modules: " + matchingVfModules)
544                                 String lowestUnusedIndex = taskProcessor.utils.getLowestUnusedIndex(matchingVfModules)
545                                 return Integer.parseInt(lowestUnusedIndex)
546                         }
547                 }
548                 else {
549                         return 0
550                 }
551         }
552 }