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