3a199216dad96526efcc2dd7358613e9a4e66209
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2018 Huawei Technologies Co., Ltd. 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.infrastructure.scripts;
24
25 import static org.apache.commons.lang3.StringUtils.*;
26
27 import javax.ws.rs.NotFoundException
28
29 import org.apache.commons.lang3.*
30 import org.camunda.bpm.engine.delegate.BpmnError
31 import org.camunda.bpm.engine.delegate.DelegateExecution
32 import org.json.JSONArray
33 import org.json.JSONObject
34 import org.onap.aai.domain.yang.ServiceInstance
35 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
36 import org.onap.so.bpmn.common.scripts.ExceptionUtil
37 import org.onap.so.bpmn.common.scripts.MsoUtils
38 import org.onap.so.bpmn.core.WorkflowException
39 import org.onap.so.bpmn.core.domain.Resource
40 import org.onap.so.bpmn.core.json.JsonUtils
41 import org.onap.so.bpmn.core.UrnPropertiesReader
42 import org.onap.aaiclient.client.aai.AAIObjectType
43 import org.onap.aaiclient.client.aai.AAIResourcesClient
44 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
45 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
46 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
47 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
48 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types
49 import org.springframework.web.util.UriUtils
50 import org.slf4j.Logger
51 import org.slf4j.LoggerFactory
52
53 import groovy.json.*
54
55 /**
56  * This groovy class supports the <class>UpdateCustomE2EServiceInstance.bpmn</class> process.
57  * AlaCarte flow for 1702 ServiceInstance Update
58  *
59  */
60 public class UpdateCustomE2EServiceInstance extends AbstractServiceTaskProcessor {
61         private static final Logger logger = LoggerFactory.getLogger( UpdateCustomE2EServiceInstance.class);
62
63         String Prefix="UPDSI_"
64         ExceptionUtil exceptionUtil = new ExceptionUtil()
65         JsonUtils jsonUtil = new JsonUtils()
66
67
68         public void preProcessRequest (DelegateExecution execution) {
69                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
70                 execution.setVariable("prefix",Prefix)
71                 String msg = ""
72                 logger.info( " *** preProcessRequest() *** ")
73
74                 try {
75
76                         String siRequest = execution.getVariable("bpmnRequest")
77
78                         String requestId = execution.getVariable("mso-request-id")
79                         execution.setVariable("msoRequestId", requestId)
80                         logger.info( "Input Request:" + siRequest + " reqId:" + requestId)
81
82                         String serviceInstanceId = execution.getVariable("serviceInstanceId")
83                         if (isBlank(serviceInstanceId)) {
84                                 msg = "Input serviceInstanceId' is null"
85                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
86                         }
87
88                         //subscriberInfo for aai
89                         String globalSubscriberId = jsonUtil.getJsonValue(siRequest, "requestDetails.subscriberInfo.globalSubscriberId")
90                         if (isBlank(globalSubscriberId)) {
91                                 msg = "Input globalSubscriberId' is null"
92                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
93                         } else {
94                                 execution.setVariable("globalSubscriberId", globalSubscriberId)
95                         }
96
97                         //requestDetails
98                         execution.setVariable("source", jsonUtil.getJsonValue(siRequest, "requestDetails.requestInfo.source"))
99                         execution.setVariable("serviceInstanceName", jsonUtil.getJsonValue(siRequest, "requestDetails.requestInfo.instanceName"))
100                         execution.setVariable("disableRollback", jsonUtil.getJsonValue(siRequest, "requestDetails.requestInfo.suppressRollback"))
101                         String productFamilyId = jsonUtil.getJsonValue(siRequest, "requestDetails.requestInfo.productFamilyId")
102                         if (isBlank(productFamilyId))
103                         {
104                                 msg = "Input productFamilyId is null"
105                                 logger.info( msg)
106                         } else {
107                                 execution.setVariable("productFamilyId", productFamilyId)
108                         }
109
110                          //user params
111                  String userParams = jsonUtil.getJsonValue(siRequest, "requestDetails.requestParameters.userParams")
112              logger.info( "userParams:" + userParams)
113                  List<String> paramList = jsonUtil.StringArrayToList(execution, userParams)
114                  String uuiRequest = jsonUtil.getJsonValue(paramList.get(0), "UUIRequest")
115                         if (isBlank(uuiRequest)) {
116                                 msg = "Input uuiRequest is null"
117                                 logger.info( msg)
118                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
119                         } else
120                         {
121                                 execution.setVariable("uuiRequest", uuiRequest)
122                         }
123
124                         logger.info( "uuiRequest:\n" + uuiRequest)
125
126                         //serviceType for aai
127                         String serviceType = jsonUtil.getJsonValue(uuiRequest, "service.serviceType")
128                         if (isBlank(serviceType)) {
129                                 msg = "Input serviceType is null"
130                                 logger.info( msg)
131                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
132                         } else {
133                                 execution.setVariable("serviceType", serviceType)
134                         }
135
136                         // target model info
137                         String modelInvariantUuid = jsonUtil.getJsonValue(uuiRequest, "service.serviceInvariantUuid")
138                         logger.info("modelInvariantUuid: " + modelInvariantUuid)
139                         execution.setVariable("modelInvariantUuid", modelInvariantUuid)
140                         execution.setVariable("model-invariant-id-target", modelInvariantUuid)
141
142                         String modelUuid = jsonUtil.getJsonValue(uuiRequest, "service.serviceUuid")
143                         logger.info("modelUuid: " + modelUuid)
144                         execution.setVariable("modelUuid", modelUuid)
145                         execution.setVariable("model-version-id-target", modelUuid)
146
147                         String serviceModelName = jsonUtil.getJsonValue(uuiRequest, "service.parameters.templateName")
148                         logger.info("serviceModelName: " + serviceModelName)
149                         if(serviceModelName == null) {
150                                 serviceModelName = ""
151                         }
152                         execution.setVariable("serviceModelName", serviceModelName)
153
154                         //operationId
155                         String operationId = jsonUtil.getJsonValue(siRequest, "operationId")
156                         if (isBlank(operationId)) {
157                                 operationId = UUID.randomUUID().toString()
158                          }
159                         execution.setVariable("operationId", operationId)
160                         execution.setVariable("operationType", "update")
161                         execution.setVariable("hasResourcetoUpdate", false)
162
163                 } catch (BpmnError e) {
164                         throw e;
165                 } catch (Exception ex){
166                         msg = "Exception in preProcessRequest " + ex.getMessage()
167                         logger.info( msg)
168                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
169                 }
170                 logger.info(" ***** Exit preProcessRequest *****")
171         }
172
173         /**
174          * Gets the service instance and its relationships from aai
175          */
176         public void getServiceInstance(DelegateExecution execution) {
177                 try {
178                         String serviceInstanceId = execution.getVariable('serviceInstanceId')
179                         String globalSubscriberId = execution.getVariable('globalSubscriberId')
180                         String serviceType = execution.getVariable('serviceType')
181
182                         AAIResourcesClient resourceClient = new AAIResourcesClient()
183                         AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(globalSubscriberId).serviceSubscription(serviceType).serviceInstance(serviceInstanceId))
184                         AAIResultWrapper wrapper = resourceClient.get(serviceInstanceUri, NotFoundException.class)
185
186                         Optional<ServiceInstance> si = wrapper.asBean(ServiceInstance.class)
187                         execution.setVariable("serviceInstanceName", si.get().getServiceInstanceName())
188                         execution.setVariable("model-invariant-id-original", si.get().getModelInvariantId())
189                         execution.setVariable("model-version-id-original", si.get().getModelVersionId())
190
191                         JSONObject ob = new JSONObject(wrapper.getJson())
192                         JSONArray ar = ob.getJSONObject("relationship-list").getJSONArray("relationship")
193
194                         execution.setVariable("serviceInstanceData-original", si.get())
195                         execution.setVariable("serviceRelationShip", ar.toString())
196
197
198                 }catch(BpmnError e) {
199                         throw e;
200                 }catch(NotFoundException e) {
201                         exceptionUtil.buildAndThrowWorkflowException(execution, 404, "Service-instance does not exist AAI")
202                 }catch(Exception ex) {
203                         String msg = "Internal Error in getServiceInstance: " + ex.getMessage()
204                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
205                 }
206         }
207
208         public void preCompareModelVersions(DelegateExecution execution) {
209                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
210         }
211
212         public void postCompareModelVersions(DelegateExecution execution) {
213                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
214                 logger.debug( " ======== STARTED postCompareModelVersions Process ======== ")
215
216                 def hasResourcetoUpdate = false
217                 def hasResourcetoAdd = false
218                 def hasResourcetoDelete = false
219                 List<Resource> addResourceList =  execution.getVariable("addResourceList")
220                 List<Resource> delResourceList =  execution.getVariable("delResourceList")
221
222                 if(addResourceList != null && !addResourceList.isEmpty()) {
223                         hasResourcetoAdd = true
224                 }
225
226                 if(delResourceList != null && !delResourceList.isEmpty()) {
227                         hasResourcetoDelete = true
228                 }
229
230                 hasResourcetoUpdate = hasResourcetoAdd || hasResourcetoDelete
231                 execution.setVariable("hasResourcetoUpdate", hasResourcetoUpdate)
232
233                 logger.debug( "======== COMPLETED postCompareModelVersions Process ======== ")
234         }
235
236         /**
237          * Init the service Operation Status
238          */
239         public void prepareInitServiceOperationStatus(DelegateExecution execution){
240                 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
241                 logger.debug( " ======== STARTED prepareInitServiceOperationStatus Process ======== ")
242                 try{
243                         String serviceId = execution.getVariable("serviceInstanceId")
244                         String operationId = execution.getVariable("operationId")
245                         String operationType = execution.getVariable("operationType")
246                         String userId = ""
247                         String result = "processing"
248                         String progress = "0"
249                         String reason = ""
250                         String operationContent = "Prepare service updating"
251                         logger.debug( "Generated new operation for Service Instance serviceId:" + serviceId + " operationId:" + operationId)
252                         serviceId = UriUtils.encode(serviceId,"UTF-8")
253                         execution.setVariable("serviceInstanceId", serviceId)
254                         execution.setVariable("operationId", operationId)
255                         execution.setVariable("operationType", operationType)
256
257                         def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
258                         execution.setVariable("CVFMI_dbAdapterEndpoint", dbAdapterEndpoint)
259                         logger.debug( "DB Adapter Endpoint is: " + dbAdapterEndpoint)
260
261                         String payload =
262                                 """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
263                         xmlns:ns="http://org.onap.so/requestsdb">
264                         <soapenv:Header/>
265                         <soapenv:Body>
266                             <ns:updateServiceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
267                             <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
268                             <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
269                             <operationType>${MsoUtils.xmlEscape(operationType)}</operationType>
270                             <userId>${MsoUtils.xmlEscape(userId)}</userId>
271                             <result>${MsoUtils.xmlEscape(result)}</result>
272                             <operationContent>${MsoUtils.xmlEscape(operationContent)}</operationContent>
273                             <progress>${MsoUtils.xmlEscape(progress)}</progress>
274                             <reason>${MsoUtils.xmlEscape(reason)}</reason>
275                         </ns:updateServiceOperationStatus>
276                     </soapenv:Body>
277                 </soapenv:Envelope>"""
278
279                         payload = utils.formatXml(payload)
280                         execution.setVariable("CVFMI_updateServiceOperStatusRequest", payload)
281                         logger.error( "Outgoing updateServiceOperStatusRequest: \n" + payload)
282
283                 }catch(Exception e){
284                         logger.debug( "Exception Occured Processing prepareInitServiceOperationStatus. Exception is:\n" + e)
285                         execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during prepareInitServiceOperationStatus Method:\n" + e.getMessage())
286                 }
287                 logger.debug( "======== COMPLETED prepareInitServiceOperationStatus Process ======== ")
288         }
289
290         /**
291          * Update the service Operation Status
292          */
293         public void preUpdateServiceOperationStatus(DelegateExecution execution){
294                 def method = getClass().getSimpleName() + '.preUpdateServiceOperationStatus(' +'execution=' + execution.getId() +')'
295                 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
296                 logger.info("Entered " + method)
297
298                 try{
299                         String serviceId = execution.getVariable("serviceInstanceId")
300                         String operationId = execution.getVariable("operationId")
301                         String operationType = execution.getVariable("operationType")
302                         String serviceName = execution.getVariable("serviceInstanceName")
303                         String result = execution.getVariable("operationResult")
304                         String progress = execution.getVariable("progress")
305                         String reason = execution.getVariable("operationReason")
306                         String userId = ""
307                         logger.info( "progress: " + progress )
308
309                         String operationContent = "Prepare service : " + execution.getVariable("operationStatus")
310
311                         logger.info( "Generated new operation for Service Instance serviceId:" + serviceId + " operationId:" + operationId)
312                         serviceId = UriUtils.encode(serviceId,"UTF-8")
313                         execution.setVariable("serviceInstanceId", serviceId)
314                         execution.setVariable("operationId", operationId)
315                         execution.setVariable("operationType", operationType)
316
317             def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
318             execution.setVariable("CVFMI_dbAdapterEndpoint", dbAdapterEndpoint)
319                         logger.info( "DB Adapter Endpoint is: " + dbAdapterEndpoint)
320
321                         String payload =
322                                 """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
323                         xmlns:ns="http://org.onap.so/requestsdb">
324                         <soapenv:Header/>
325                         <soapenv:Body>
326                             <ns:updateServiceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
327                             <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
328                             <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
329                             <operationType>${MsoUtils.xmlEscape(operationType)}</operationType>
330                             <userId>${MsoUtils.xmlEscape(userId)}</userId>
331                             <result>${MsoUtils.xmlEscape(result)}</result>
332                             <operationContent>${MsoUtils.xmlEscape(operationContent)}</operationContent>
333                             <progress>${MsoUtils.xmlEscape(progress)}</progress>
334                             <reason>${MsoUtils.xmlEscape(reason)}</reason>
335                         </ns:updateServiceOperationStatus>
336                     </soapenv:Body>
337                 </soapenv:Envelope>"""
338
339                         payload = utils.formatXml(payload)
340                         execution.setVariable("CVFMI_updateServiceOperStatusRequest", payload)
341                         logger.error( "Outgoing preUpdateServiceOperationStatus: \n" + payload)
342
343
344                 }catch(Exception e){
345                         logger.info( "Exception Occured Processing preUpdateServiceOperationStatus. Exception is:\n" + e)
346                         execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during preUpdateServiceOperationStatus Method:\n" + e.getMessage())
347                 }
348                 logger.info( "======== COMPLETED preUpdateServiceOperationStatus Process ======== ")
349                 logger.info( "Exited " + method)
350         }
351
352         public void sendSyncResponse (DelegateExecution execution) {
353                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
354                 logger.info( " *** sendSyncResponse *** ")
355
356                 try {
357                         String operationId = execution.getVariable("operationId")
358                         def hasResourcetoUpdate = execution.getVariable("hasResourcetoUpdate")
359
360                         String updateServiceResp = ""
361                         if(hasResourcetoUpdate) {
362                                 // RESTResponse for API Handler (APIH) Reply Task
363                                 updateServiceResp = """{"operationId":"${operationId}"}""".trim()
364                         }
365                         else {
366                                 updateServiceResp =  """{"OperationResult":"No Resource to Add or Delete or Service Instance not found in AAI."}"""
367                         }
368
369                         logger.info( " sendSyncResponse to APIH:" + "\n" + updateServiceResp)
370                         sendWorkflowResponse(execution, 202, updateServiceResp)
371                         execution.setVariable("sentSyncResponse", true)
372
373                 } catch (Exception ex) {
374                         String msg = "Exceptuion in sendSyncResponse:" + ex.getMessage()
375                         logger.info( msg)
376                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
377                 }
378                 logger.info(" ***** Exit sendSyncResopnse *****")
379         }
380
381         public void sendSyncError (DelegateExecution execution) {
382                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
383                 logger.info( " *** sendSyncError *** ")
384
385                 try {
386                         String errorMessage = ""
387                         int errorCode = 7000
388                         if (execution.getVariable("WorkflowException") instanceof WorkflowException) {
389                                 WorkflowException wfe = execution.getVariable("WorkflowException")
390                                 errorMessage = wfe.getErrorMessage()
391                                 errorCode = wfe.getErrorCode()
392                         } else {
393                                 errorMessage = "Sending Sync Error."
394                         }
395
396                         String buildworkflowException =
397                                         """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
398                                         <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
399                                         <aetgt:ErrorCode>${MsoUtils.xmlEscape(errorCode)}</aetgt:ErrorCode>
400                                    </aetgt:WorkflowException>"""
401
402                         sendWorkflowResponse(execution, 500, buildworkflowException)
403
404                 } catch (Exception ex) {
405                         logger.info( " Sending Sync Error Activity Failed. " + "\n" + ex.getMessage())
406                 }
407
408         }
409
410         public void prepareCompletionRequest (DelegateExecution execution) {
411                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
412                 logger.info( " *** prepareCompletion *** ")
413
414                 try {
415                         String requestId = execution.getVariable("msoRequestId")
416                         String serviceInstanceId = execution.getVariable("serviceInstanceId")
417                         String source = execution.getVariable("source")
418
419                         String msoCompletionRequest =
420                                         """<aetgt:MsoCompletionRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
421                                                                 xmlns:ns="http://org.onap/so/request/types/v1">
422                                                 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
423                                                         <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
424                                                         <action>UPDATE</action>
425                                                         <source>${MsoUtils.xmlEscape(source)}</source>
426                                                 </request-info>
427                                                 <status-message>Service Instance was updated successfully.</status-message>
428                                                 <serviceInstanceId>${MsoUtils.xmlEscape(serviceInstanceId)}</serviceInstanceId>
429                                                 <mso-bpel-name>UpdateCustomE2EServiceInstance</mso-bpel-name>
430                                         </aetgt:MsoCompletionRequest>"""
431
432                         // Format Response
433                         String xmlMsoCompletionRequest = utils.formatXml(msoCompletionRequest)
434
435                         execution.setVariable("completionRequest", xmlMsoCompletionRequest)
436                         logger.info( " Overall SUCCESS Response going to CompleteMsoProcess - " + "\n" + xmlMsoCompletionRequest)
437
438                 } catch (Exception ex) {
439                         String msg = " Exception in prepareCompletion:" + ex.getMessage()
440                         logger.info( msg)
441                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
442                 }
443                 logger.info( "*** Exit prepareCompletionRequest ***")
444         }
445
446         public void prepareFalloutRequest(DelegateExecution execution){
447                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
448                 logger.info( " *** prepareFalloutRequest *** ")
449
450                 try {
451                         WorkflowException wfex = execution.getVariable("WorkflowException")
452                         logger.info( " Input Workflow Exception: " + wfex.toString())
453                         String requestId = execution.getVariable("msoRequestId")
454                         String source = execution.getVariable("source")
455                         String requestInfo =
456                                         """<request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
457                                         <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
458                                         <action>UPDATE</action>
459                                         <source>${MsoUtils.xmlEscape(source)}</source>
460                                    </request-info>"""
461
462                         String falloutRequest = exceptionUtil.processMainflowsBPMNException(execution, requestInfo)
463                         execution.setVariable("falloutRequest", falloutRequest)
464                 } catch (Exception ex) {
465                         logger.info( "Exception prepareFalloutRequest:" + ex.getMessage())
466                         String errorException = "  Bpmn error encountered in UpdateCustomE2EServiceInstance flow. FalloutHandlerRequest,  buildErrorResponse() - " + ex.getMessage()
467                         String requestId = execution.getVariable("msoRequestId")
468                         String falloutRequest =
469                                         """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
470                                                                      xmlns:ns="http://org.onap/so/request/types/v1"
471                                                                      xmlns:wfsch="http://org.onap/so/workflow/schema/v1">
472                                            <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
473                                               <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
474                                               <action>UPDATE</action>
475                                               <source>UUI</source>
476                                            </request-info>
477                                                 <aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
478                                                         <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorException)}</aetgt:ErrorMessage>
479                                                         <aetgt:ErrorCode>7000</aetgt:ErrorCode>
480                                                 </aetgt:WorkflowException>
481                                         </aetgt:FalloutHandlerRequest>"""
482
483                         execution.setVariable("falloutRequest", falloutRequest)
484                 }
485                 logger.info( "*** Exit prepareFalloutRequest ***")
486         }
487 }