8cdc2aaaf446d02465ca2cc073ba3e110dd00754
[so.git] / mso-api-handlers / mso-api-handler-infra / src / main / java / org / onap / so / apihandlerinfra / RequestHandlerUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7  * Modifications Copyright (C) 2019 IBM.
8  * ================================================================================
9  * Modifications Copyright (c) 2019 Samsung
10  * ================================================================================
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  * 
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  * 
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.so.apihandlerinfra;
26
27
28 import static org.onap.so.logger.HttpHeadersConstants.REQUESTOR_ID;
29 import java.io.IOException;
30 import java.net.URL;
31 import java.sql.Timestamp;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Optional;
37 import javax.ws.rs.container.ContainerRequestContext;
38 import javax.ws.rs.core.MultivaluedMap;
39 import javax.ws.rs.core.Response;
40 import org.apache.commons.lang.StringUtils;
41 import org.apache.http.HttpResponse;
42 import org.apache.http.HttpStatus;
43 import org.camunda.bpm.engine.history.HistoricProcessInstance;
44 import org.camunda.bpm.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
45 import org.onap.logging.ref.slf4j.ONAPLogConstants;
46 import org.onap.so.apihandler.camundabeans.CamundaResponse;
47 import org.onap.so.apihandler.common.CommonConstants;
48 import org.onap.so.apihandler.common.ErrorNumbers;
49 import org.onap.so.apihandler.common.RequestClient;
50 import org.onap.so.apihandler.common.RequestClientFactory;
51 import org.onap.so.apihandler.common.RequestClientParameter;
52 import org.onap.so.apihandler.common.ResponseBuilder;
53 import org.onap.so.apihandler.common.ResponseHandler;
54 import org.onap.so.apihandlerinfra.exceptions.ApiException;
55 import org.onap.so.apihandlerinfra.exceptions.BPMNFailureException;
56 import org.onap.so.apihandlerinfra.exceptions.ClientConnectionException;
57 import org.onap.so.apihandlerinfra.exceptions.ContactCamundaException;
58 import org.onap.so.apihandlerinfra.exceptions.DuplicateRequestException;
59 import org.onap.so.apihandlerinfra.exceptions.RecipeNotFoundException;
60 import org.onap.so.apihandlerinfra.exceptions.RequestDbFailureException;
61 import org.onap.so.apihandlerinfra.exceptions.ValidateException;
62 import org.onap.so.apihandlerinfra.exceptions.VfModuleNotFoundException;
63 import org.onap.so.apihandlerinfra.infra.rest.handler.AbstractRestHandler;
64 import org.onap.so.apihandlerinfra.logging.ErrorLoggerInfo;
65 import org.onap.so.constants.Status;
66 import org.onap.so.db.catalog.beans.NetworkResource;
67 import org.onap.so.db.catalog.beans.NetworkResourceCustomization;
68 import org.onap.so.db.catalog.beans.Recipe;
69 import org.onap.so.db.catalog.beans.ServiceRecipe;
70 import org.onap.so.db.catalog.beans.VfModule;
71 import org.onap.so.db.catalog.beans.VfModuleCustomization;
72 import org.onap.so.db.catalog.beans.VnfRecipe;
73 import org.onap.so.db.catalog.beans.VnfResource;
74 import org.onap.so.db.catalog.beans.VnfResourceCustomization;
75 import org.onap.so.db.catalog.client.CatalogDbClient;
76 import org.onap.so.db.request.beans.InfraActiveRequests;
77 import org.onap.so.db.request.client.RequestsDbClient;
78 import org.onap.so.exceptions.ValidationException;
79 import org.onap.so.logger.ErrorCode;
80 import org.onap.so.logger.LogConstants;
81 import org.onap.so.logger.MessageEnum;
82 import org.onap.so.serviceinstancebeans.CloudConfiguration;
83 import org.onap.so.serviceinstancebeans.ModelInfo;
84 import org.onap.so.serviceinstancebeans.ModelType;
85 import org.onap.so.serviceinstancebeans.Networks;
86 import org.onap.so.serviceinstancebeans.RelatedInstance;
87 import org.onap.so.serviceinstancebeans.RelatedInstanceList;
88 import org.onap.so.serviceinstancebeans.RequestDetails;
89 import org.onap.so.serviceinstancebeans.RequestParameters;
90 import org.onap.so.serviceinstancebeans.Service;
91 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
92 import org.onap.so.serviceinstancebeans.ServiceInstancesResponse;
93 import org.onap.so.serviceinstancebeans.VfModules;
94 import org.onap.so.serviceinstancebeans.Vnfs;
95 import org.onap.so.utils.UUIDChecker;
96 import org.slf4j.Logger;
97 import org.slf4j.LoggerFactory;
98 import org.slf4j.MDC;
99 import org.springframework.beans.factory.annotation.Autowired;
100 import org.springframework.core.env.Environment;
101 import org.springframework.http.ResponseEntity;
102 import org.springframework.stereotype.Component;
103 import org.springframework.web.client.RestClientException;
104 import com.fasterxml.jackson.annotation.JsonInclude.Include;
105 import com.fasterxml.jackson.databind.ObjectMapper;
106
107 @Component
108 public class RequestHandlerUtils extends AbstractRestHandler {
109
110     private static Logger logger = LoggerFactory.getLogger(RequestHandlerUtils.class);
111
112     private static final String SAVE_TO_DB = "save instance to db";
113     private static final String NAME = "name";
114     private static final String VALUE = "value";
115
116     @Autowired
117     private Environment env;
118
119     @Autowired
120     private RequestClientFactory reqClientFactory;
121
122     @Autowired
123     private RequestsDbClient infraActiveRequestsClient;
124
125     @Autowired
126     private ResponseBuilder builder;
127
128     @Autowired
129     private MsoRequest msoRequest;
130
131     @Autowired
132     private CamundaRequestHandler camundaRequestHandler;
133
134     @Autowired
135     private CatalogDbClient catalogDbClient;
136
137     public Response postBPELRequest(InfraActiveRequests currentActiveReq, RequestClientParameter requestClientParameter,
138             String orchestrationUri, String requestScope) throws ApiException {
139         HttpResponse response = null;
140         RequestClient requestClient = null;
141
142         try {
143             requestClient = reqClientFactory.getRequestClient(orchestrationUri);
144             response = requestClient.post(requestClientParameter);
145         } catch (Exception e) {
146             logger.error("Error posting request to BPMN", e);
147             ErrorLoggerInfo errorLoggerInfo =
148                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR, ErrorCode.AvailabilityError)
149                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
150             String url = requestClient != null ? requestClient.getUrl() : "";
151             ClientConnectionException clientException =
152                     new ClientConnectionException.Builder(url, HttpStatus.SC_BAD_GATEWAY,
153                             ErrorNumbers.SVC_NO_SERVER_RESOURCES).cause(e).errorInfo(errorLoggerInfo).build();
154             updateStatus(currentActiveReq, Status.FAILED, clientException.getMessage());
155             throw clientException;
156         }
157
158         if (response == null) {
159
160             ErrorLoggerInfo errorLoggerInfo = new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_COMMUNICATE_ERROR,
161                     ErrorCode.BusinessProcesssError).errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
162             ClientConnectionException clientException = new ClientConnectionException.Builder(requestClient.getUrl(),
163                     HttpStatus.SC_BAD_GATEWAY, ErrorNumbers.SVC_NO_SERVER_RESOURCES).errorInfo(errorLoggerInfo).build();
164             updateStatus(currentActiveReq, Status.FAILED, clientException.getMessage());
165             throw clientException;
166         }
167
168         ResponseHandler respHandler = null;
169         int bpelStatus = 500;
170         try {
171             respHandler = new ResponseHandler(response, requestClient.getType());
172             bpelStatus = respHandler.getStatus();
173         } catch (ApiException e) {
174             logger.error("Exception occurred", e);
175             ErrorLoggerInfo errorLoggerInfo =
176                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
177                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
178             ValidateException validateException =
179                     new ValidateException.Builder("Exception caught mapping Camunda JSON response to object",
180                             HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER).cause(e)
181                                     .errorInfo(errorLoggerInfo).build();
182             updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
183             throw validateException;
184         }
185
186         // BPEL accepted the request, the request is in progress
187         if (bpelStatus == HttpStatus.SC_ACCEPTED) {
188             ServiceInstancesResponse jsonResponse;
189             CamundaResponse camundaResp = respHandler.getResponse();
190
191             if ("Success".equalsIgnoreCase(camundaResp.getMessage())) {
192                 try {
193                     ObjectMapper mapper = new ObjectMapper();
194                     jsonResponse = mapper.readValue(camundaResp.getResponse(), ServiceInstancesResponse.class);
195                     jsonResponse.getRequestReferences().setRequestId(requestClientParameter.getRequestId());
196                     Optional<URL> selfLinkUrl =
197                             buildSelfLinkUrl(currentActiveReq.getRequestUrl(), requestClientParameter.getRequestId());
198                     if (selfLinkUrl.isPresent()) {
199                         jsonResponse.getRequestReferences().setRequestSelfLink(selfLinkUrl.get());
200                     } else {
201                         jsonResponse.getRequestReferences().setRequestSelfLink(null);
202                     }
203                 } catch (IOException e) {
204                     logger.error("Exception occurred", e);
205                     ErrorLoggerInfo errorLoggerInfo =
206                             new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
207                                     .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
208                     ValidateException validateException =
209                             new ValidateException.Builder("Exception caught mapping Camunda JSON response to object",
210                                     HttpStatus.SC_NOT_ACCEPTABLE, ErrorNumbers.SVC_BAD_PARAMETER).cause(e)
211                                             .errorInfo(errorLoggerInfo).build();
212                     updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
213                     throw validateException;
214                 }
215                 return builder.buildResponse(HttpStatus.SC_ACCEPTED, requestClientParameter.getRequestId(),
216                         jsonResponse, requestClientParameter.getApiVersion());
217             }
218         }
219
220         List<String> variables = new ArrayList<>();
221         variables.add(bpelStatus + "");
222         String camundaJSONResponseBody = respHandler.getResponseBody();
223         if (camundaJSONResponseBody != null && !camundaJSONResponseBody.isEmpty()) {
224
225             ErrorLoggerInfo errorLoggerInfo =
226                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.BusinessProcesssError)
227                             .errorSource(requestClient.getUrl()).build();
228             BPMNFailureException bpmnException =
229                     new BPMNFailureException.Builder(String.valueOf(bpelStatus) + camundaJSONResponseBody, bpelStatus,
230                             ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).errorInfo(errorLoggerInfo).build();
231
232             updateStatus(currentActiveReq, Status.FAILED, bpmnException.getMessage());
233
234             throw bpmnException;
235         } else {
236
237             ErrorLoggerInfo errorLoggerInfo =
238                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.BusinessProcesssError)
239                             .errorSource(requestClient.getUrl()).build();
240
241
242             BPMNFailureException servException = new BPMNFailureException.Builder(String.valueOf(bpelStatus),
243                     bpelStatus, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).errorInfo(errorLoggerInfo).build();
244             updateStatus(currentActiveReq, Status.FAILED, servException.getMessage());
245
246             throw servException;
247         }
248     }
249
250
251
252     @Override
253     public void updateStatus(InfraActiveRequests aq, Status status, String errorMessage)
254             throws RequestDbFailureException {
255         if ((status == Status.FAILED) || (status == Status.COMPLETE)) {
256             aq.setStatusMessage(errorMessage);
257             aq.setProgress(new Long(100));
258             aq.setRequestStatus(status.toString());
259             Timestamp endTimeStamp = new Timestamp(System.currentTimeMillis());
260             aq.setEndTime(endTimeStamp);
261             try {
262                 infraActiveRequestsClient.save(aq);
263             } catch (Exception e) {
264                 ErrorLoggerInfo errorLoggerInfo =
265                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
266                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
267                 throw new RequestDbFailureException.Builder(SAVE_TO_DB, e.toString(),
268                         HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
269                                 .errorInfo(errorLoggerInfo).build();
270             }
271         }
272     }
273
274     public String deriveRequestScope(Actions action, ServiceInstancesRequest sir, String requestUri) {
275         if (action == Action.inPlaceSoftwareUpdate || action == Action.applyUpdatedConfig) {
276             return (ModelType.vnf.name());
277         } else if (action == Action.addMembers || action == Action.removeMembers) {
278             return (ModelType.instanceGroup.toString());
279         } else {
280             String requestScope;
281             if (sir.getRequestDetails().getModelInfo().getModelType() == null) {
282                 requestScope = requestScopeFromUri(requestUri);
283             } else {
284                 requestScope = sir.getRequestDetails().getModelInfo().getModelType().name();
285             }
286             return requestScope;
287         }
288     }
289
290
291     public void validateHeaders(ContainerRequestContext context) throws ValidationException {
292         MultivaluedMap<String, String> headers = context.getHeaders();
293         if (!headers.containsKey(ONAPLogConstants.Headers.REQUEST_ID)) {
294             throw new ValidationException(ONAPLogConstants.Headers.REQUEST_ID + " header", true);
295         }
296         if (!headers.containsKey(ONAPLogConstants.Headers.PARTNER_NAME)) {
297             throw new ValidationException(ONAPLogConstants.Headers.PARTNER_NAME + " header", true);
298         }
299         if (!headers.containsKey(REQUESTOR_ID)) {
300             throw new ValidationException(REQUESTOR_ID + " header", true);
301         }
302     }
303
304     public String getRequestUri(ContainerRequestContext context, String uriPrefix) {
305         String requestUri = context.getUriInfo().getPath();
306         String httpUrl = MDC.get(LogConstants.URI_BASE).concat(requestUri);
307         MDC.put(LogConstants.HTTP_URL, httpUrl);
308         requestUri = requestUri.substring(requestUri.indexOf(uriPrefix) + uriPrefix.length());
309         return requestUri;
310     }
311
312     public InfraActiveRequests duplicateCheck(Actions action, HashMap<String, String> instanceIdMap,
313             String instanceName, String requestScope, InfraActiveRequests currentActiveReq) throws ApiException {
314         InfraActiveRequests dup = null;
315         try {
316             if (!(instanceName == null && "service".equals(requestScope) && (action == Action.createInstance
317                     || action == Action.activateInstance || action == Action.assignInstance))) {
318                 dup = infraActiveRequestsClient.checkInstanceNameDuplicate(instanceIdMap, instanceName, requestScope);
319             }
320         } catch (Exception e) {
321             ErrorLoggerInfo errorLoggerInfo =
322                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DUPLICATE_CHECK_EXC, ErrorCode.DataError)
323                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
324             RequestDbFailureException requestDbFailureException =
325                     new RequestDbFailureException.Builder("check for duplicate instance", e.toString(),
326                             HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
327                                     .errorInfo(errorLoggerInfo).build();
328             updateStatus(currentActiveReq, Status.FAILED, requestDbFailureException.getMessage());
329             throw requestDbFailureException;
330         }
331         return dup;
332     }
333
334     public boolean camundaHistoryCheck(InfraActiveRequests duplicateRecord, InfraActiveRequests currentActiveReq)
335             throws RequestDbFailureException, ContactCamundaException {
336         String requestId = duplicateRecord.getRequestId();
337         ResponseEntity<List<HistoricProcessInstanceEntity>> response = null;
338         try {
339             response = camundaRequestHandler.getCamundaProcessInstanceHistory(requestId);
340         } catch (RestClientException e) {
341             logger.error("Error querying Camunda for process-instance history for requestId: {}, exception: {}",
342                     requestId, e.getMessage());
343             ContactCamundaException contactCamundaException =
344                     new ContactCamundaException.Builder("process-instance", requestId, e.toString(),
345                             HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR).cause(e)
346                                     .build();
347             updateStatus(currentActiveReq, Status.FAILED, contactCamundaException.getMessage());
348             throw contactCamundaException;
349         }
350
351         if (response.getBody().isEmpty()) {
352             updateStatus(duplicateRecord, Status.COMPLETE, "Request Completed");
353         }
354         for (HistoricProcessInstance instance : response.getBody()) {
355             if (("ACTIVE").equals(instance.getState())) {
356                 return true;
357             } else {
358                 updateStatus(duplicateRecord, Status.COMPLETE, "Request Completed");
359             }
360         }
361         return false;
362     }
363
364     public ServiceInstancesRequest convertJsonToServiceInstanceRequest(String requestJSON, Actions action,
365             String requestId, String requestUri) throws ApiException {
366         try {
367             ObjectMapper mapper = new ObjectMapper();
368             return mapper.readValue(requestJSON, ServiceInstancesRequest.class);
369
370         } catch (IOException e) {
371
372             ErrorLoggerInfo errorLoggerInfo =
373                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
374                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
375
376             ValidateException validateException =
377                     new ValidateException.Builder("Error mapping request: " + e.getMessage(), HttpStatus.SC_BAD_REQUEST,
378                             ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
379             String requestScope = requestScopeFromUri(requestUri);
380
381             msoRequest.createErrorRequestRecord(Status.FAILED, requestId, validateException.getMessage(), action,
382                     requestScope, requestJSON);
383
384             throw validateException;
385         }
386     }
387
388     public void parseRequest(ServiceInstancesRequest sir, HashMap<String, String> instanceIdMap, Actions action,
389             String version, String requestJSON, Boolean aLaCarte, String requestId,
390             InfraActiveRequests currentActiveReq) throws ValidateException, RequestDbFailureException {
391         int reqVersion = Integer.parseInt(version.substring(1));
392         try {
393             msoRequest.parse(sir, instanceIdMap, action, version, requestJSON, reqVersion, aLaCarte);
394         } catch (Exception e) {
395             logger.error("failed to parse request", e);
396             ErrorLoggerInfo errorLoggerInfo =
397                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
398                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
399             ValidateException validateException =
400                     new ValidateException.Builder("Error parsing request: " + e.getMessage(), HttpStatus.SC_BAD_REQUEST,
401                             ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
402
403             updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
404
405             throw validateException;
406         }
407     }
408
409     public void buildErrorOnDuplicateRecord(InfraActiveRequests currentActiveReq, Actions action,
410             HashMap<String, String> instanceIdMap, String instanceName, String requestScope, InfraActiveRequests dup)
411             throws ApiException {
412
413         String instance = null;
414         if (instanceName != null) {
415             instance = instanceName;
416         } else {
417             instance = instanceIdMap.get(requestScope + "InstanceId");
418         }
419         ErrorLoggerInfo errorLoggerInfo =
420                 new ErrorLoggerInfo.Builder(MessageEnum.APIH_DUPLICATE_FOUND, ErrorCode.SchemaError)
421                         .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
422
423         DuplicateRequestException dupException =
424                 new DuplicateRequestException.Builder(requestScope, instance, dup.getRequestStatus(),
425                         dup.getRequestId(), HttpStatus.SC_CONFLICT, ErrorNumbers.SVC_DETAILED_SERVICE_ERROR)
426                                 .errorInfo(errorLoggerInfo).build();
427
428         updateStatus(currentActiveReq, Status.FAILED, dupException.getMessage());
429
430         throw dupException;
431     }
432
433     @Override
434     public String getRequestId(ContainerRequestContext requestContext) throws ValidateException {
435         String requestId = null;
436         if (requestContext.getProperty("requestId") != null) {
437             requestId = requestContext.getProperty("requestId").toString();
438         }
439         if (UUIDChecker.isValidUUID(requestId)) {
440             return requestId;
441         } else {
442             ErrorLoggerInfo errorLoggerInfo =
443                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_BPEL_RESPONSE_ERROR, ErrorCode.SchemaError)
444                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
445             ValidateException validateException =
446                     new ValidateException.Builder("Request Id " + requestId + " is not a valid UUID",
447                             HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorNumbers.SVC_BAD_PARAMETER)
448                                     .errorInfo(errorLoggerInfo).build();
449
450             throw validateException;
451         }
452     }
453
454     public void setInstanceId(InfraActiveRequests currentActiveReq, String requestScope, String instanceId,
455             Map<String, String> instanceIdMap) {
456         if (StringUtils.isNotBlank(instanceId)) {
457             if (ModelType.service.name().equalsIgnoreCase(requestScope)) {
458                 currentActiveReq.setServiceInstanceId(instanceId);
459             } else if (ModelType.vnf.name().equalsIgnoreCase(requestScope)) {
460                 currentActiveReq.setVnfId(instanceId);
461             } else if (ModelType.vfModule.name().equalsIgnoreCase(requestScope)) {
462                 currentActiveReq.setVfModuleId(instanceId);
463             } else if (ModelType.volumeGroup.name().equalsIgnoreCase(requestScope)) {
464                 currentActiveReq.setVolumeGroupId(instanceId);
465             } else if (ModelType.network.name().equalsIgnoreCase(requestScope)) {
466                 currentActiveReq.setNetworkId(instanceId);
467             } else if (ModelType.configuration.name().equalsIgnoreCase(requestScope)) {
468                 currentActiveReq.setConfigurationId(instanceId);
469             } else if (ModelType.instanceGroup.toString().equalsIgnoreCase(requestScope)) {
470                 currentActiveReq.setInstanceGroupId(instanceId);
471             }
472         } else if (instanceIdMap != null && !instanceIdMap.isEmpty()) {
473             if (instanceIdMap.get("serviceInstanceId") != null) {
474                 currentActiveReq.setServiceInstanceId(instanceIdMap.get("serviceInstanceId"));
475             }
476             if (instanceIdMap.get("vnfInstanceId") != null) {
477                 currentActiveReq.setVnfId(instanceIdMap.get("vnfInstanceId"));
478             }
479             if (instanceIdMap.get("vfModuleInstanceId") != null) {
480                 currentActiveReq.setVfModuleId(instanceIdMap.get("vfModuleInstanceId"));
481             }
482             if (instanceIdMap.get("volumeGroupInstanceId") != null) {
483                 currentActiveReq.setVolumeGroupId(instanceIdMap.get("volumeGroupInstanceId"));
484             }
485             if (instanceIdMap.get("networkInstanceId") != null) {
486                 currentActiveReq.setNetworkId(instanceIdMap.get("networkInstanceId"));
487             }
488             if (instanceIdMap.get("configurationInstanceId") != null) {
489                 currentActiveReq.setConfigurationId(instanceIdMap.get("configurationInstanceId"));
490             }
491             if (instanceIdMap.get(CommonConstants.INSTANCE_GROUP_INSTANCE_ID) != null) {
492                 currentActiveReq.setInstanceGroupId(instanceIdMap.get(CommonConstants.INSTANCE_GROUP_INSTANCE_ID));
493             }
494         }
495     }
496
497     public String mapJSONtoMSOStyle(String msoRawRequest, ServiceInstancesRequest serviceInstRequest,
498             boolean isAlaCarte, Actions action) throws IOException {
499         ObjectMapper mapper = new ObjectMapper();
500         mapper.setSerializationInclusion(Include.NON_NULL);
501         if (serviceInstRequest != null) {
502             return mapper.writeValueAsString(serviceInstRequest);
503         } else {
504             return msoRawRequest;
505         }
506     }
507
508     public Optional<String> retrieveModelName(RequestParameters requestParams) {
509         String requestTestApi = null;
510         TestApi testApi = null;
511
512         if (requestParams != null) {
513             requestTestApi = requestParams.getTestApi();
514         }
515
516         if (requestTestApi == null) {
517             if (requestParams != null && requestParams.getALaCarte() != null && !requestParams.getALaCarte()) {
518                 requestTestApi = env.getProperty(CommonConstants.MACRO_TEST_API);
519             } else {
520                 requestTestApi = env.getProperty(CommonConstants.ALACARTE_TEST_API);
521             }
522         }
523
524         try {
525             testApi = TestApi.valueOf(requestTestApi);
526             return Optional.of(testApi.getModelName());
527         } catch (Exception e) {
528             logger.warn("Catching the exception on the valueOf enum call and continuing", e);
529             throw new IllegalArgumentException("Invalid TestApi is provided", e);
530         }
531     }
532
533     public String getDefaultModel(ServiceInstancesRequest sir) {
534         String defaultModel = sir.getRequestDetails().getRequestInfo().getSource() + "_DEFAULT";
535         Optional<String> oModelName = retrieveModelName(sir.getRequestDetails().getRequestParameters());
536         if (oModelName.isPresent()) {
537             defaultModel = oModelName.get();
538         }
539         return defaultModel;
540     }
541
542     public String getServiceType(String requestScope, ServiceInstancesRequest sir, Boolean aLaCarteFlag) {
543         String serviceType = null;
544         if (requestScope.equalsIgnoreCase(ModelType.service.toString())) {
545             String defaultServiceModelName = getDefaultModel(sir);
546             org.onap.so.db.catalog.beans.Service serviceRecord;
547             if (aLaCarteFlag) {
548                 serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
549                 if (serviceRecord != null) {
550                     serviceType = serviceRecord.getServiceType();
551                 }
552             } else {
553                 serviceRecord =
554                         catalogDbClient.getServiceByID(sir.getRequestDetails().getModelInfo().getModelVersionId());
555                 if (serviceRecord != null) {
556                     serviceType = serviceRecord.getServiceType();
557                 } else {
558                     serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
559                     if (serviceRecord != null) {
560                         serviceType = serviceRecord.getServiceType();
561                     }
562                 }
563             }
564         } else {
565             serviceType = msoRequest.getServiceInstanceType(sir, requestScope);
566         }
567         return serviceType;
568     }
569
570     protected String setServiceInstanceId(String requestScope, ServiceInstancesRequest sir) {
571         if (sir.getServiceInstanceId() != null) {
572             return sir.getServiceInstanceId();
573         } else if (requestScope.equalsIgnoreCase(ModelType.instanceGroup.toString())) {
574             RelatedInstanceList[] relatedInstances = sir.getRequestDetails().getRelatedInstanceList();
575             if (relatedInstances != null) {
576                 for (RelatedInstanceList relatedInstanceList : relatedInstances) {
577                     RelatedInstance relatedInstance = relatedInstanceList.getRelatedInstance();
578                     if (relatedInstance.getModelInfo().getModelType() == ModelType.service) {
579                         return relatedInstance.getInstanceId();
580                     }
581                 }
582             }
583         }
584         return null;
585     }
586
587     private String requestScopeFromUri(String requestUri) {
588         String requestScope;
589         if (requestUri.contains(ModelType.network.name())) {
590             requestScope = ModelType.network.name();
591         } else if (requestUri.contains(ModelType.vfModule.name())) {
592             requestScope = ModelType.vfModule.name();
593         } else if (requestUri.contains(ModelType.volumeGroup.name())) {
594             requestScope = ModelType.volumeGroup.name();
595         } else if (requestUri.contains(ModelType.configuration.name())) {
596             requestScope = ModelType.configuration.name();
597         } else if (requestUri.contains(ModelType.vnf.name())) {
598             requestScope = ModelType.vnf.name();
599         } else {
600             requestScope = ModelType.service.name();
601         }
602         return requestScope;
603     }
604
605     protected InfraActiveRequests createNewRecordCopyFromInfraActiveRequest(InfraActiveRequests infraActiveRequest,
606             String requestId, Timestamp startTimeStamp, String source, String requestUri, String requestorId,
607             String originalRequestId) throws ApiException {
608         InfraActiveRequests request = new InfraActiveRequests();
609         request.setRequestId(requestId);
610         request.setStartTime(startTimeStamp);
611         request.setSource(source);
612         request.setRequestUrl(requestUri);
613         request.setProgress(new Long(5));
614         request.setRequestorId(requestorId);
615         request.setRequestStatus(Status.IN_PROGRESS.toString());
616         request.setOriginalRequestId(originalRequestId);
617         request.setLastModifiedBy(Constants.MODIFIED_BY_APIHANDLER);
618         if (infraActiveRequest != null) {
619             request.setTenantId(infraActiveRequest.getTenantId());
620             request.setRequestBody(updateRequestorIdInRequestBody(infraActiveRequest, requestorId));
621             request.setAicCloudRegion(infraActiveRequest.getAicCloudRegion());
622             request.setRequestScope(infraActiveRequest.getRequestScope());
623             request.setRequestAction(infraActiveRequest.getRequestAction());
624             setInstanceIdAndName(infraActiveRequest, request);
625         }
626         return request;
627     }
628
629     protected void setInstanceIdAndName(InfraActiveRequests infraActiveRequest,
630             InfraActiveRequests currentActiveRequest) throws ApiException {
631         String requestScope = infraActiveRequest.getRequestScope();
632         try {
633             ModelType type = ModelType.valueOf(requestScope);
634             String instanceName = type.getName(infraActiveRequest);
635             if (instanceName == null && type.equals(ModelType.vfModule)) {
636                 logger.error("vfModule for requestId: {} being resumed does not have an instanceName.",
637                         infraActiveRequest.getRequestId());
638                 ValidateException validateException = new ValidateException.Builder(
639                         "vfModule for requestId: " + infraActiveRequest.getRequestId()
640                                 + " being resumed does not have an instanceName.",
641                         HttpStatus.SC_BAD_REQUEST, ErrorNumbers.SVC_BAD_PARAMETER).build();
642                 updateStatus(currentActiveRequest, Status.FAILED, validateException.getMessage());
643                 throw validateException;
644             }
645             if (instanceName != null) {
646                 type.setName(currentActiveRequest, instanceName);
647             }
648             type.setId(currentActiveRequest, type.getId(infraActiveRequest));
649         } catch (IllegalArgumentException e) {
650             logger.error(
651                     "requestScope \"{}\" does not match a ModelType enum. Unable to set instanceId and instanceName from the original request.",
652                     requestScope);
653         }
654     }
655
656     protected Boolean getIsBaseVfModule(ModelInfo modelInfo, Actions action, String vnfType,
657             String sdcServiceModelVersion, InfraActiveRequests currentActiveReq) throws ApiException {
658         // Get VF Module-specific base module indicator
659         VfModule vfm = null;
660         String modelVersionId = modelInfo.getModelVersionId();
661         Boolean isBaseVfModule = false;
662
663         if (modelVersionId != null) {
664             vfm = catalogDbClient.getVfModuleByModelUUID(modelVersionId);
665         } else if (modelInfo.getModelInvariantId() != null && modelInfo.getModelVersion() != null) {
666             vfm = catalogDbClient.getVfModuleByModelInvariantUUIDAndModelVersion(modelInfo.getModelInvariantId(),
667                     modelInfo.getModelVersion());
668         }
669
670         if (vfm != null) {
671             if (vfm.getIsBase()) {
672                 isBaseVfModule = true;
673             }
674         } else if (action == Action.createInstance || action == Action.updateInstance) {
675             String serviceVersionText = "";
676             if (sdcServiceModelVersion != null && !sdcServiceModelVersion.isEmpty()) {
677                 serviceVersionText = " with version " + sdcServiceModelVersion;
678             }
679             String errorMessage = "VnfType " + vnfType + " and VF Module Model Name " + modelInfo.getModelName()
680                     + serviceVersionText + " not found in MSO Catalog DB";
681             ErrorLoggerInfo errorLoggerInfo =
682                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ATTRIBUTE_NOT_FOUND, ErrorCode.DataError)
683                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
684             VfModuleNotFoundException vfModuleException = new VfModuleNotFoundException.Builder(errorMessage,
685                     HttpStatus.SC_NOT_FOUND, ErrorNumbers.SVC_BAD_PARAMETER).errorInfo(errorLoggerInfo).build();
686             updateStatus(currentActiveReq, Status.FAILED, vfModuleException.getMessage());
687             throw vfModuleException;
688         }
689         return isBaseVfModule;
690     }
691
692     protected ModelType getModelType(Actions action, ModelInfo modelInfo) {
693         if (action == Action.applyUpdatedConfig || action == Action.inPlaceSoftwareUpdate) {
694             return ModelType.vnf;
695         } else if (action == Action.addMembers || action == Action.removeMembers) {
696             return ModelType.instanceGroup;
697         } else {
698             return modelInfo.getModelType();
699         }
700     }
701
702     protected String updateRequestorIdInRequestBody(InfraActiveRequests infraActiveRequest, String newRequestorId) {
703         String requestBody = infraActiveRequest.getRequestBody();
704         return requestBody.replaceAll(
705                 "(?s)(\"requestInfo\"\\s*?:\\s*?\\{.*?\"requestorId\"\\s*?:\\s*?\")(.*?)(\"[ ]*(?:,|\\R|\\}))",
706                 "$1" + newRequestorId + "$3");
707     }
708
709     public RecipeLookupResult getServiceInstanceOrchestrationURI(ServiceInstancesRequest sir, Actions action,
710             boolean alaCarteFlag, InfraActiveRequests currentActiveReq) throws ApiException {
711         RecipeLookupResult recipeLookupResult = null;
712         // if the aLaCarte flag is set to TRUE, the API-H should choose the VID_DEFAULT recipe for the requested action
713         ModelInfo modelInfo = sir.getRequestDetails().getModelInfo();
714         // Query MSO Catalog DB
715
716         if (action == Action.applyUpdatedConfig || action == Action.inPlaceSoftwareUpdate) {
717             recipeLookupResult = getDefaultVnfUri(sir, action);
718         } else if (action == Action.addMembers || action == Action.removeMembers) {
719             recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
720         } else if (modelInfo.getModelType().equals(ModelType.service)) {
721             try {
722                 recipeLookupResult = getServiceURI(sir, action, alaCarteFlag);
723             } catch (IOException e) {
724                 ErrorLoggerInfo errorLoggerInfo =
725                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
726                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
727
728
729                 ValidateException validateException =
730                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
731                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
732
733                 updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
734
735                 throw validateException;
736             }
737         } else if (modelInfo.getModelType().equals(ModelType.vfModule)
738                 || modelInfo.getModelType().equals(ModelType.volumeGroup)
739                 || modelInfo.getModelType().equals(ModelType.vnf)) {
740             try {
741                 recipeLookupResult = getVnfOrVfModuleUri(sir, action);
742             } catch (ValidationException e) {
743                 ErrorLoggerInfo errorLoggerInfo =
744                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
745                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
746
747
748                 ValidateException validateException =
749                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
750                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
751
752                 updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
753
754                 throw validateException;
755             }
756         } else if (modelInfo.getModelType().equals(ModelType.network)) {
757             try {
758                 recipeLookupResult = getNetworkUri(sir, action);
759             } catch (ValidationException e) {
760
761                 ErrorLoggerInfo errorLoggerInfo =
762                         new ErrorLoggerInfo.Builder(MessageEnum.APIH_REQUEST_VALIDATION_ERROR, ErrorCode.SchemaError)
763                                 .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
764
765
766                 ValidateException validateException =
767                         new ValidateException.Builder(e.getMessage(), HttpStatus.SC_BAD_REQUEST,
768                                 ErrorNumbers.SVC_BAD_PARAMETER).cause(e).errorInfo(errorLoggerInfo).build();
769                 updateStatus(currentActiveReq, Status.FAILED, validateException.getMessage());
770
771                 throw validateException;
772             }
773         } else if (modelInfo.getModelType().equals(ModelType.instanceGroup)) {
774             recipeLookupResult = new RecipeLookupResult("/mso/async/services/WorkflowActionBB", 180);
775         }
776
777         if (recipeLookupResult == null) {
778             ErrorLoggerInfo errorLoggerInfo =
779                     new ErrorLoggerInfo.Builder(MessageEnum.APIH_DB_ACCESS_EXC, ErrorCode.DataError)
780                             .errorSource(Constants.MSO_PROP_APIHANDLER_INFRA).build();
781
782
783             RecipeNotFoundException recipeNotFoundExceptionException =
784                     new RecipeNotFoundException.Builder("Recipe could not be retrieved from catalog DB.",
785                             HttpStatus.SC_NOT_FOUND, ErrorNumbers.SVC_GENERAL_SERVICE_ERROR).errorInfo(errorLoggerInfo)
786                                     .build();
787
788             updateStatus(currentActiveReq, Status.FAILED, recipeNotFoundExceptionException.getMessage());
789             throw recipeNotFoundExceptionException;
790         }
791         return recipeLookupResult;
792     }
793
794     protected RecipeLookupResult getServiceURI(ServiceInstancesRequest servInstReq, Actions action,
795             boolean alaCarteFlag) throws IOException {
796         // SERVICE REQUEST
797         // Construct the default service name
798         // TODO need to make this a configurable property
799         String defaultServiceModelName = getDefaultModel(servInstReq);
800         RequestDetails requestDetails = servInstReq.getRequestDetails();
801         ModelInfo modelInfo = requestDetails.getModelInfo();
802         org.onap.so.db.catalog.beans.Service serviceRecord;
803         List<org.onap.so.db.catalog.beans.Service> serviceRecordList;
804         ServiceRecipe recipe = null;
805
806         if (alaCarteFlag) {
807             serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
808             if (serviceRecord != null) {
809                 recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(serviceRecord.getModelUUID(),
810                         action.toString());
811             }
812         } else {
813             serviceRecord = catalogDbClient.getServiceByID(modelInfo.getModelVersionId());
814             recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(modelInfo.getModelVersionId(),
815                     action.toString());
816             if (recipe == null) {
817                 serviceRecordList = catalogDbClient
818                         .getServiceByModelInvariantUUIDOrderByModelVersionDesc(modelInfo.getModelInvariantId());
819                 if (!serviceRecordList.isEmpty()) {
820                     for (org.onap.so.db.catalog.beans.Service record : serviceRecordList) {
821                         recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(record.getModelUUID(),
822                                 action.toString());
823                         if (recipe != null) {
824                             break;
825                         }
826                     }
827                 }
828             }
829         }
830
831         // if an aLaCarte flag was sent in the request, throw an error if the recipe was not found
832         RequestParameters reqParam = requestDetails.getRequestParameters();
833         if (reqParam != null && alaCarteFlag && recipe == null) {
834             return null;
835         } else if (!alaCarteFlag && recipe != null && Action.createInstance.equals(action)) {
836             mapToLegacyRequest(requestDetails);
837         } else if (recipe == null) { // aLaCarte wasn't sent, so we'll try the default
838             serviceRecord = catalogDbClient.getFirstByModelNameOrderByModelVersionDesc(defaultServiceModelName);
839             recipe = catalogDbClient.getFirstByServiceModelUUIDAndAction(serviceRecord.getModelUUID(),
840                     action.toString());
841         }
842         if (modelInfo.getModelVersionId() == null) {
843             modelInfo.setModelVersionId(serviceRecord.getModelUUID());
844         }
845         if (recipe == null) {
846             return null;
847         }
848         return new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout());
849     }
850
851     protected void mapToLegacyRequest(RequestDetails requestDetails) throws IOException {
852         RequestParameters reqParam;
853         if (requestDetails.getRequestParameters() == null) {
854             reqParam = new RequestParameters();
855         } else {
856             reqParam = requestDetails.getRequestParameters();
857         }
858         if (requestDetails.getCloudConfiguration() == null) {
859             CloudConfiguration cloudConfig = configureCloudConfig(reqParam);
860             if (cloudConfig != null) {
861                 requestDetails.setCloudConfiguration(cloudConfig);
862             }
863         }
864
865         List<Map<String, Object>> userParams = configureUserParams(reqParam);
866         if (!userParams.isEmpty()) {
867             if (reqParam == null) {
868                 requestDetails.setRequestParameters(new RequestParameters());
869             }
870             requestDetails.getRequestParameters().setUserParams(userParams);
871         }
872     }
873
874     private Service serviceMapper(Map<String, Object> params) throws IOException {
875         ObjectMapper obj = new ObjectMapper();
876         String input = obj.writeValueAsString(params.get("service"));
877         return obj.readValue(input, Service.class);
878     }
879
880     private void addUserParams(Map<String, Object> targetUserParams, List<Map<String, String>> sourceUserParams) {
881         for (Map<String, String> map : sourceUserParams) {
882             for (Map.Entry<String, String> entry : map.entrySet()) {
883                 targetUserParams.put(entry.getKey(), entry.getValue());
884             }
885         }
886     }
887
888     protected List<Map<String, Object>> configureUserParams(RequestParameters reqParams) throws IOException {
889         logger.debug("Configuring UserParams for Macro Request");
890         Map<String, Object> userParams = new HashMap<>();
891
892         for (Map<String, Object> params : reqParams.getUserParams()) {
893             if (params.containsKey("service")) {
894                 Service service = serviceMapper(params);
895
896                 addUserParams(userParams, service.getInstanceParams());
897
898                 for (Networks network : service.getResources().getNetworks()) {
899                     addUserParams(userParams, network.getInstanceParams());
900                 }
901
902                 for (Vnfs vnf : service.getResources().getVnfs()) {
903                     addUserParams(userParams, vnf.getInstanceParams());
904
905                     for (VfModules vfModule : vnf.getVfModules()) {
906                         addUserParams(userParams, vfModule.getInstanceParams());
907                     }
908                 }
909             }
910         }
911
912         return mapFlatMapToNameValue(userParams);
913     }
914
915     protected List<Map<String, Object>> mapFlatMapToNameValue(Map<String, Object> flatMap) {
916         List<Map<String, Object>> targetUserParams = new ArrayList<>();
917
918         for (Map.Entry<String, Object> map : flatMap.entrySet()) {
919             Map<String, Object> targetMap = new HashMap<>();
920             targetMap.put(NAME, map.getKey());
921             targetMap.put(VALUE, map.getValue());
922             targetUserParams.add(targetMap);
923         }
924         return targetUserParams;
925     }
926
927     protected CloudConfiguration configureCloudConfig(RequestParameters reqParams) throws IOException {
928
929         for (Map<String, Object> params : reqParams.getUserParams()) {
930             if (params.containsKey("service")) {
931                 Service service = serviceMapper(params);
932
933                 Optional<CloudConfiguration> targetConfiguration = addCloudConfig(service.getCloudConfiguration());
934
935                 if (targetConfiguration.isPresent()) {
936                     return targetConfiguration.get();
937                 } else {
938                     for (Networks network : service.getResources().getNetworks()) {
939                         targetConfiguration = addCloudConfig(network.getCloudConfiguration());
940                         if (targetConfiguration.isPresent()) {
941                             return targetConfiguration.get();
942                         }
943                     }
944
945                     for (Vnfs vnf : service.getResources().getVnfs()) {
946                         targetConfiguration = addCloudConfig(vnf.getCloudConfiguration());
947
948                         if (targetConfiguration.isPresent()) {
949                             return targetConfiguration.get();
950                         }
951
952                         for (VfModules vfModule : vnf.getVfModules()) {
953                             targetConfiguration = addCloudConfig(vfModule.getCloudConfiguration());
954
955                             if (targetConfiguration.isPresent()) {
956                                 return targetConfiguration.get();
957                             }
958                         }
959                     }
960                 }
961             }
962         }
963
964         return null;
965     }
966
967     private RecipeLookupResult getDefaultVnfUri(ServiceInstancesRequest sir, Actions action) {
968         String defaultSource = getDefaultModel(sir);
969         VnfRecipe vnfRecipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
970         if (vnfRecipe == null) {
971             return null;
972         }
973         return new RecipeLookupResult(vnfRecipe.getOrchestrationUri(), vnfRecipe.getRecipeTimeout());
974     }
975
976
977     private RecipeLookupResult getNetworkUri(ServiceInstancesRequest sir, Actions action) throws ValidationException {
978         String defaultNetworkType = getDefaultModel(sir);
979         ModelInfo modelInfo = sir.getRequestDetails().getModelInfo();
980         String modelName = modelInfo.getModelName();
981         Recipe recipe = null;
982
983         if (modelInfo.getModelCustomizationId() != null) {
984             NetworkResourceCustomization networkResourceCustomization = catalogDbClient
985                     .getNetworkResourceCustomizationByModelCustomizationUUID(modelInfo.getModelCustomizationId());
986             if (networkResourceCustomization != null) {
987                 NetworkResource networkResource = networkResourceCustomization.getNetworkResource();
988                 if (networkResource != null) {
989                     if (modelInfo.getModelVersionId() == null) {
990                         modelInfo.setModelVersionId(networkResource.getModelUUID());
991                     }
992                     recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(networkResource.getModelName(),
993                             action.toString());
994                 } else {
995                     throw new ValidationException("no catalog entry found");
996                 }
997             } else if (action != Action.deleteInstance) {
998                 throw new ValidationException("modelCustomizationId for networkResourceCustomization lookup", true);
999             }
1000         } else {
1001             // ok for version < 3 and action delete
1002             if (modelName != null) {
1003                 recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(modelName, action.toString());
1004             }
1005         }
1006
1007         if (recipe == null) {
1008             recipe = catalogDbClient.getFirstNetworkRecipeByModelNameAndAction(defaultNetworkType, action.toString());
1009         }
1010
1011         return recipe != null ? new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout()) : null;
1012     }
1013
1014
1015     private Optional<CloudConfiguration> addCloudConfig(CloudConfiguration sourceCloudConfiguration) {
1016         CloudConfiguration targetConfiguration = new CloudConfiguration();
1017         if (sourceCloudConfiguration != null) {
1018             targetConfiguration.setAicNodeClli(sourceCloudConfiguration.getAicNodeClli());
1019             targetConfiguration.setTenantId(sourceCloudConfiguration.getTenantId());
1020             targetConfiguration.setLcpCloudRegionId(sourceCloudConfiguration.getLcpCloudRegionId());
1021             targetConfiguration.setCloudOwner(sourceCloudConfiguration.getCloudOwner());
1022             return Optional.of(targetConfiguration);
1023         }
1024         return Optional.empty();
1025     }
1026
1027     private RecipeLookupResult getVnfOrVfModuleUri(ServiceInstancesRequest servInstReq, Actions action)
1028             throws ValidationException {
1029
1030         ModelInfo modelInfo = servInstReq.getRequestDetails().getModelInfo();
1031         String vnfComponentType = modelInfo.getModelType().name();
1032
1033         RelatedInstanceList[] instanceList = null;
1034         if (servInstReq.getRequestDetails() != null) {
1035             instanceList = servInstReq.getRequestDetails().getRelatedInstanceList();
1036         }
1037
1038         Recipe recipe;
1039         String defaultSource = getDefaultModel(servInstReq);
1040         String modelCustomizationId = modelInfo.getModelCustomizationId();
1041         String modelCustomizationName = modelInfo.getModelCustomizationName();
1042         String relatedInstanceModelVersionId = null;
1043         String relatedInstanceModelInvariantId = null;
1044         String relatedInstanceVersion = null;
1045         String relatedInstanceModelCustomizationName = null;
1046
1047         if (instanceList != null) {
1048
1049             for (RelatedInstanceList relatedInstanceList : instanceList) {
1050
1051                 RelatedInstance relatedInstance = relatedInstanceList.getRelatedInstance();
1052                 ModelInfo relatedInstanceModelInfo = relatedInstance.getModelInfo();
1053                 if (relatedInstanceModelInfo.getModelType().equals(ModelType.service)) {
1054                     relatedInstanceModelVersionId = relatedInstanceModelInfo.getModelVersionId();
1055                     relatedInstanceVersion = relatedInstanceModelInfo.getModelVersion();
1056                 }
1057
1058                 if (relatedInstanceModelInfo.getModelType().equals(ModelType.vnf)) {
1059                     relatedInstanceModelVersionId = relatedInstanceModelInfo.getModelVersionId();
1060                     relatedInstanceModelInvariantId = relatedInstanceModelInfo.getModelInvariantId();
1061                     relatedInstanceVersion = relatedInstanceModelInfo.getModelVersion();
1062                     relatedInstanceModelCustomizationName = relatedInstanceModelInfo.getModelCustomizationName();
1063                 }
1064             }
1065
1066             if (modelInfo.getModelType().equals(ModelType.vnf)) {
1067                 // a. For a vnf request (only create, no update currently):
1068                 // i. (v3-v4) If modelInfo.modelCustomizationId is provided, use it to validate catalog DB has record in
1069                 // vnf_resource_customization.model_customization_uuid.
1070                 // ii. (v2-v4) If modelInfo.modelCustomizationId is NOT provided (because it is a pre-1702 ASDC model or
1071                 // pre-v3), then modelInfo.modelCustomizationName must have
1072                 // been provided (else create request should be rejected). APIH should use the
1073                 // relatedInstance.modelInfo[service].modelVersionId** + modelInfo[vnf].modelCustomizationName
1074                 // to â€œjoinâ€�? service_to_resource_customizations with vnf_resource_customization to confirm a
1075                 // vnf_resource_customization.model_customization_uuid record exists.
1076                 // **If relatedInstance.modelInfo[service].modelVersionId was not provided, use
1077                 // relatedInstance.modelInfo[service].modelInvariantId + modelVersion instead to lookup modelVersionId
1078                 // (MODEL_UUID) in SERVICE table.
1079                 // iii. Regardless of how the value was provided/obtained above, APIH must always populate
1080                 // vnfModelCustomizationId in bpmnRequest. It would be assumed it was MSO generated
1081                 // during 1707 data migration if VID did not provide it originally on request.
1082                 // iv. Note: continue to construct the â€œvnf-typeâ€�? value and pass to BPMN (must still be populated
1083                 // in A&AI).
1084                 // 1. If modelCustomizationName is NOT provided on a vnf/vfModule request, use modelCustomizationId to
1085                 // look it up in our catalog to construct vnf-type value to pass to BPMN.
1086
1087                 VnfResource vnfResource = null;
1088                 VnfResourceCustomization vrc = null;
1089                 // Validation for vnfResource
1090
1091                 if (modelCustomizationId != null) {
1092                     vrc = catalogDbClient.getVnfResourceCustomizationByModelCustomizationUUID(modelCustomizationId);
1093                     if (vrc != null) {
1094                         vnfResource = vrc.getVnfResources();
1095                     }
1096                 } else {
1097                     org.onap.so.db.catalog.beans.Service service =
1098                             catalogDbClient.getServiceByID(relatedInstanceModelVersionId);
1099                     if (service == null) {
1100                         service = catalogDbClient.getServiceByModelVersionAndModelInvariantUUID(relatedInstanceVersion,
1101                                 relatedInstanceModelInvariantId);
1102                     }
1103
1104                     if (service == null) {
1105                         throw new ValidationException("service in relatedInstance");
1106                     }
1107                     for (VnfResourceCustomization vnfResourceCustom : service.getVnfCustomizations()) {
1108                         if (vnfResourceCustom.getModelInstanceName().equals(modelCustomizationName)) {
1109                             vrc = vnfResourceCustom;
1110                         }
1111                     }
1112
1113                     if (vrc != null) {
1114                         vnfResource = vrc.getVnfResources();
1115                         modelInfo.setModelCustomizationId(vrc.getModelCustomizationUUID());
1116                         modelInfo.setModelCustomizationUuid(vrc.getModelCustomizationUUID());
1117                     }
1118                 }
1119
1120                 if (vnfResource == null) {
1121                     throw new ValidationException("vnfResource");
1122                 } else {
1123                     if (modelInfo.getModelVersionId() == null) {
1124                         modelInfo.setModelVersionId(vnfResource.getModelUUID());
1125                     }
1126                 }
1127
1128                 VnfRecipe vnfRecipe = null;
1129
1130                 if (vrc != null) {
1131                     String nfRole = vrc.getNfRole();
1132                     if (nfRole != null) {
1133                         vnfRecipe =
1134                                 catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(vrc.getNfRole(), action.toString());
1135                     }
1136                 }
1137
1138                 if (vnfRecipe == null) {
1139                     vnfRecipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
1140                 }
1141
1142                 if (vnfRecipe == null) {
1143                     return null;
1144                 }
1145
1146                 return new RecipeLookupResult(vnfRecipe.getOrchestrationUri(), vnfRecipe.getRecipeTimeout());
1147             } else {
1148                 /*
1149                  * (v5-v7) If modelInfo.modelCustomizationId is NOT provided (because it is a pre-1702 ASDC model or
1150                  * pre-v3), then modelInfo.modelCustomizationName must have // been provided (else create request should
1151                  * be rejected). APIH should use the relatedInstance.modelInfo[vnf].modelVersionId +
1152                  * modelInfo[vnf].modelCustomizationName // to join vnf_to_resource_customizations with
1153                  * vf_resource_customization to confirm a vf_resource_customization.model_customization_uuid record
1154                  * exists. // Once the vnfs model_customization_uuid has been obtained, use it to find all vfModule
1155                  * customizations for that vnf customization in the vnf_res_custom_to_vf_module_custom join table. //
1156                  * For each vf_module_cust_model_customization_uuid value returned, use that UUID to query
1157                  * vf_module_customization table along with modelInfo[vfModule|volumeGroup].modelVersionId to // confirm
1158                  * record matches request data (and to identify the modelCustomizationId associated with the vfModule in
1159                  * the request). This means taking each record found // in vf_module_customization and looking up in
1160                  * vf_module (using vf_module_customization’s FK into vf_module) to find a match on
1161                  * MODEL_INVARIANT_UUID (modelInvariantId) // and MODEL_VERSION (modelVersion).
1162                  */
1163                 VfModuleCustomization vfmc = null;
1164                 VnfResource vnfr;
1165                 VnfResourceCustomization vnfrc;
1166                 VfModule vfModule = null;
1167
1168                 if (modelInfo.getModelCustomizationId() != null) {
1169                     vfmc = catalogDbClient
1170                             .getVfModuleCustomizationByModelCuztomizationUUID(modelInfo.getModelCustomizationId());
1171                 } else {
1172                     vnfr = catalogDbClient.getVnfResourceByModelUUID(relatedInstanceModelVersionId);
1173                     if (vnfr == null) {
1174                         vnfr = catalogDbClient.getFirstVnfResourceByModelInvariantUUIDAndModelVersion(
1175                                 relatedInstanceModelInvariantId, relatedInstanceVersion);
1176                     }
1177                     vnfrc = catalogDbClient.getFirstVnfResourceCustomizationByModelInstanceNameAndVnfResources(
1178                             relatedInstanceModelCustomizationName, vnfr);
1179
1180                     List<VfModuleCustomization> list = vnfrc.getVfModuleCustomizations();
1181
1182                     String vfModuleModelUUID = modelInfo.getModelVersionId();
1183                     for (VfModuleCustomization vf : list) {
1184                         VfModuleCustomization vfmCustom;
1185                         if (vfModuleModelUUID != null) {
1186                             vfmCustom = catalogDbClient
1187                                     .getVfModuleCustomizationByModelCustomizationUUIDAndVfModuleModelUUID(
1188                                             vf.getModelCustomizationUUID(), vfModuleModelUUID);
1189                             if (vfmCustom != null) {
1190                                 vfModule = vfmCustom.getVfModule();
1191                             }
1192                         } else {
1193                             vfmCustom = catalogDbClient
1194                                     .getVfModuleCustomizationByModelCuztomizationUUID(vf.getModelCustomizationUUID());
1195                             if (vfmCustom != null) {
1196                                 vfModule = vfmCustom.getVfModule();
1197                             } else {
1198                                 vfModule = catalogDbClient.getVfModuleByModelInvariantUUIDAndModelVersion(
1199                                         relatedInstanceModelInvariantId, relatedInstanceVersion);
1200                             }
1201                         }
1202
1203                         if (vfModule != null) {
1204                             modelInfo.setModelCustomizationId(vf.getModelCustomizationUUID());
1205                             modelInfo.setModelCustomizationUuid(vf.getModelCustomizationUUID());
1206                             break;
1207                         }
1208                     }
1209                 }
1210
1211                 if (vfmc == null && vfModule == null) {
1212                     throw new ValidationException("vfModuleCustomization");
1213                 } else if (vfModule == null && vfmc != null) {
1214                     vfModule = vfmc.getVfModule(); // can't be null as vfModuleModelUUID is not-null property in
1215                                                    // VfModuleCustomization table
1216                 }
1217
1218                 if (modelInfo.getModelVersionId() == null) {
1219                     modelInfo.setModelVersionId(vfModule.getModelUUID());
1220                 }
1221
1222
1223                 recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1224                         vfModule.getModelUUID(), vnfComponentType, action.toString());
1225                 if (recipe == null) {
1226                     List<VfModule> vfModuleRecords = catalogDbClient
1227                             .getVfModuleByModelInvariantUUIDOrderByModelVersionDesc(vfModule.getModelInvariantUUID());
1228                     if (!vfModuleRecords.isEmpty()) {
1229                         for (VfModule record : vfModuleRecords) {
1230                             recipe = catalogDbClient
1231                                     .getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1232                                             record.getModelUUID(), vnfComponentType, action.toString());
1233                             if (recipe != null) {
1234                                 break;
1235                             }
1236                         }
1237                     }
1238                 }
1239                 if (recipe == null) {
1240                     recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1241                             defaultSource, vnfComponentType, action.toString());
1242                     if (recipe == null) {
1243                         recipe = catalogDbClient.getFirstVnfComponentsRecipeByVnfComponentTypeAndAction(
1244                                 vnfComponentType, action.toString());
1245                     }
1246
1247                     if (recipe == null) {
1248                         return null;
1249                     }
1250                 }
1251             }
1252         } else {
1253
1254             if (modelInfo.getModelType().equals(ModelType.vnf)) {
1255                 recipe = catalogDbClient.getFirstVnfRecipeByNfRoleAndAction(defaultSource, action.toString());
1256                 if (recipe == null) {
1257                     return null;
1258                 }
1259             } else {
1260                 recipe = catalogDbClient.getFirstVnfComponentsRecipeByVfModuleModelUUIDAndVnfComponentTypeAndAction(
1261                         defaultSource, vnfComponentType, action.toString());
1262
1263                 if (recipe == null) {
1264                     return null;
1265                 }
1266             }
1267         }
1268
1269         return new RecipeLookupResult(recipe.getOrchestrationUri(), recipe.getRecipeTimeout());
1270     }
1271 }