Merge "retry on ResponseProcessingException"
[so.git] / bpmn / so-bpmn-tasks / src / main / java / org / onap / so / bpmn / infrastructure / workflow / tasks / WorkflowAction.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Modifications Copyright (c) 2021 Nokia
10  * ================================================================================
11  * Modifications Copyright (c) 2020 Tech Mahindra
12  * ================================================================================
13  * Licensed under the Apache License, Version 2.0 (the "License");
14  * you may not use this file except in compliance with the License.
15  * You may obtain a copy of the License at
16  *
17  *      http://www.apache.org/licenses/LICENSE-2.0
18  *
19  * Unless required by applicable law or agreed to in writing, software
20  * distributed under the License is distributed on an "AS IS" BASIS,
21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  * See the License for the specific language governing permissions and
23  * limitations under the License.
24  * ============LICENSE_END=========================================================
25  */
26
27 package org.onap.so.bpmn.infrastructure.workflow.tasks;
28
29 import com.fasterxml.jackson.core.JsonProcessingException;
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import java.io.IOException;
32 import org.apache.commons.lang3.SerializationUtils;
33 import org.camunda.bpm.engine.delegate.DelegateExecution;
34 import org.javatuples.Pair;
35 import org.onap.aai.domain.yang.Relationship;
36 import org.onap.aai.domain.yang.ServiceInstance;
37 import org.onap.aai.domain.yang.Vnfc;
38 import org.onap.aai.domain.yang.VolumeGroup;
39 import org.onap.aai.domain.yang.VpnBinding;
40 import org.onap.aaiclient.client.aai.AAICommonObjectMapperProvider;
41 import org.onap.aaiclient.client.aai.AAIObjectName;
42 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper;
43 import org.onap.aaiclient.client.aai.entities.Relationships;
44 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
45 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
46 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder;
47 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types;
48 import org.onap.so.bpmn.common.BBConstants;
49 import org.onap.so.bpmn.infrastructure.workflow.tasks.excpetion.VnfcMultipleRelationshipException;
50 import org.onap.so.bpmn.infrastructure.workflow.tasks.utils.WorkflowResourceIdsUtils;
51 import org.onap.so.bpmn.servicedecomposition.bbobjects.Configuration;
52 import org.onap.so.bpmn.servicedecomposition.bbobjects.VfModule;
53 import org.onap.so.bpmn.servicedecomposition.entities.ExecuteBuildingBlock;
54 import org.onap.so.bpmn.servicedecomposition.entities.WorkflowResourceIds;
55 import org.onap.so.bpmn.servicedecomposition.tasks.BBInputSetup;
56 import org.onap.so.bpmn.servicedecomposition.tasks.BBInputSetupUtils;
57 import org.onap.so.client.exception.ExceptionBuilder;
58 import org.onap.so.client.orchestration.AAIConfigurationResources;
59 import org.onap.so.client.orchestration.AAIEntityNotFoundException;
60 import org.onap.so.db.catalog.beans.CollectionNetworkResourceCustomization;
61 import org.onap.so.db.catalog.beans.CollectionResourceCustomization;
62 import org.onap.so.db.catalog.beans.CollectionResourceInstanceGroupCustomization;
63 import org.onap.so.db.catalog.beans.InstanceGroup;
64 import org.onap.so.db.catalog.beans.VfModuleCustomization;
65 import org.onap.so.db.catalog.beans.macro.NorthBoundRequest;
66 import org.onap.so.db.catalog.beans.macro.OrchestrationFlow;
67 import org.onap.so.db.catalog.client.CatalogDbClient;
68 import org.onap.so.serviceinstancebeans.CloudConfiguration;
69 import org.onap.so.serviceinstancebeans.ModelInfo;
70 import org.onap.so.serviceinstancebeans.ModelType;
71 import org.onap.so.serviceinstancebeans.RelatedInstance;
72 import org.onap.so.serviceinstancebeans.RelatedInstanceList;
73 import org.onap.so.serviceinstancebeans.RequestDetails;
74 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77 import org.springframework.beans.factory.annotation.Autowired;
78 import org.springframework.core.env.Environment;
79 import org.springframework.stereotype.Component;
80 import org.springframework.util.CollectionUtils;
81 import java.util.ArrayList;
82 import java.util.Arrays;
83 import java.util.Comparator;
84 import java.util.List;
85 import java.util.Map;
86 import java.util.Optional;
87 import java.util.UUID;
88 import java.util.regex.Matcher;
89 import java.util.regex.Pattern;
90 import java.util.stream.Collectors;
91 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.ASSIGNINSTANCE;
92 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.CONTROLLER;
93 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.CREATE_INSTANCE;
94 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.FABRIC_CONFIGURATION;
95 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.NETWORKCOLLECTION;
96 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.REPLACEINSTANCE;
97 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.REPLACEINSTANCERETAINASSIGNMENTS;
98 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.SERVICE;
99 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.USER_PARAM_SERVICE;
100 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.WORKFLOW_ACTION_ERROR_MESSAGE;
101
102 @Component
103 public class WorkflowAction {
104
105     private static final Logger logger = LoggerFactory.getLogger(WorkflowAction.class);
106
107     private static final String SERVICE_INSTANCES = "serviceInstances";
108     private static final String VF_MODULES = "vfModules";
109     private static final String VNF_TYPE = "vnfType";
110     private static final String CONFIGURATION = "Configuration";
111     private static final String SUPPORTEDTYPES =
112             "vnfs|vfModules|networks|networkCollections|volumeGroups|serviceInstances|instanceGroups";
113     private static final String HOMINGSOLUTION = "Homing_Solution";
114     private static final String SERVICE_TYPE_TRANSPORT = "TRANSPORT";
115     private static final String SERVICE_TYPE_BONDING = "BONDING";
116     private static final String CLOUD_OWNER = "DEFAULT";
117     private static final String CREATENETWORKBB = "CreateNetworkBB";
118     private static final String ACTIVATENETWORKBB = "ActivateNetworkBB";
119     private static final String VOLUMEGROUP_DELETE_PATTERN = "(Un|De)(.*)Volume(.*)";
120     private static final String VOLUMEGROUP_CREATE_PATTERN = "(A|C)(.*)Volume(.*)";
121     private static final String DEFAULT_CLOUD_OWNER = "org.onap.so.cloud-owner";
122     private static final String HOMING = "homing";
123
124     @Autowired
125     protected BBInputSetup bbInputSetup;
126     @Autowired
127     protected BBInputSetupUtils bbInputSetupUtils;
128     @Autowired
129     private ExceptionBuilder exceptionBuilder;
130     @Autowired
131     private CatalogDbClient catalogDbClient;
132     @Autowired
133     private AAIConfigurationResources aaiConfigurationResources;
134     @Autowired
135     private WorkflowActionExtractResourcesAAI workflowActionUtils;
136     @Autowired
137     private VrfValidation vrfValidation;
138     @Autowired
139     private Environment environment;
140     @Autowired
141     private UserParamsServiceTraversal userParamsServiceTraversal;
142     @Autowired
143     private AaiResourceIdValidator aaiResourceIdValidator;
144     @Autowired
145     private ExecuteBuildingBlockBuilder executeBuildingBlockBuilder;
146
147     public void setBbInputSetupUtils(BBInputSetupUtils bbInputSetupUtils) {
148         this.bbInputSetupUtils = bbInputSetupUtils;
149     }
150
151     public void setBbInputSetup(BBInputSetup bbInputSetup) {
152         this.bbInputSetup = bbInputSetup;
153     }
154
155     public void selectExecutionList(DelegateExecution execution) throws Exception {
156         try {
157             fillExecutionDefault(execution);
158             final String bpmnRequest = (String) execution.getVariable(BBConstants.G_BPMN_REQUEST);
159             ServiceInstancesRequest sIRequest =
160                     new ObjectMapper().readValue(bpmnRequest, ServiceInstancesRequest.class);
161
162             final String requestId = (String) execution.getVariable(BBConstants.G_REQUEST_ID);
163
164             String uri = (String) execution.getVariable(BBConstants.G_URI);
165             boolean isResume = isUriResume(uri);
166
167             final boolean isALaCarte = (boolean) execution.getVariable(BBConstants.G_ALACARTE);
168             Resource resource = getResource(bbInputSetupUtils, isResume, isALaCarte, uri, requestId);
169
170             WorkflowResourceIds workflowResourceIds = populateResourceIdsFromApiHandler(execution);
171             RequestDetails requestDetails = sIRequest.getRequestDetails();
172             String requestAction = (String) execution.getVariable(BBConstants.G_ACTION);
173             String resourceId = getResourceId(resource, requestAction, requestDetails, workflowResourceIds);
174             WorkflowType resourceType = resource.getResourceType();
175
176             String serviceInstanceId = getServiceInstanceId(execution, resourceId, resourceType);
177
178             fillExecution(execution, requestDetails.getRequestInfo().getSuppressRollback(), resourceId, resourceType);
179             List<ExecuteBuildingBlock> flowsToExecute;
180             if (isRequestMacroServiceResume(isALaCarte, resourceType, requestAction, serviceInstanceId)) {
181                 String errorMessage = "Could not resume Macro flow. Error loading execution path.";
182                 flowsToExecute = loadExecuteBuildingBlocks(execution, requestId, errorMessage);
183             } else if (isALaCarte && isResume) {
184                 String errorMessage =
185                         "Could not resume request with request Id: " + requestId + ". No flowsToExecute was found";
186                 flowsToExecute = loadExecuteBuildingBlocks(execution, requestId, errorMessage);
187             } else {
188                 String vnfType = (String) execution.getVariable(VNF_TYPE);
189                 String cloudOwner = getCloudOwner(requestDetails.getCloudConfiguration());
190                 List<OrchestrationFlow> orchFlows =
191                         (List<OrchestrationFlow>) execution.getVariable(BBConstants.G_ORCHESTRATION_FLOW);
192                 final String apiVersion = (String) execution.getVariable(BBConstants.G_APIVERSION);
193                 final String serviceType =
194                         Optional.ofNullable((String) execution.getVariable(BBConstants.G_SERVICE_TYPE)).orElse("");
195                 if (isALaCarte) {
196                     flowsToExecute = loadExecuteBuildingBlocksForAlaCarte(orchFlows, execution, requestAction,
197                             resourceType, cloudOwner, serviceType, sIRequest, requestId, workflowResourceIds,
198                             requestDetails, resourceId, vnfType, apiVersion);
199                 } else {
200                     flowsToExecute = loadExecuteBuildingBlocksForMacro(sIRequest, resourceType, requestAction,
201                             execution, serviceInstanceId, resourceId, workflowResourceIds, orchFlows, cloudOwner,
202                             serviceType, requestId, apiVersion, vnfType, requestDetails);
203                 }
204             }
205             // If the user set "Homing_Solution" to "none", disable homing, else if "Homing_Solution" is specified,
206             // enable it.
207             if (sIRequest.getRequestDetails().getRequestParameters() != null
208                     && sIRequest.getRequestDetails().getRequestParameters().getUserParams() != null) {
209                 List<Map<String, Object>> userParams =
210                         sIRequest.getRequestDetails().getRequestParameters().getUserParams();
211                 for (Map<String, Object> params : userParams) {
212                     if (params.containsKey(HOMINGSOLUTION)) {
213                         execution.setVariable(HOMING, !"none".equals(params.get(HOMINGSOLUTION)));
214                     }
215                 }
216             }
217
218             if (CollectionUtils.isEmpty(flowsToExecute)) {
219                 throw new IllegalStateException("Macro did not come up with a valid execution path.");
220             }
221
222             List<String> flowNames = new ArrayList<>();
223             logger.info("List of BuildingBlocks to execute:");
224
225             flowsToExecute.forEach(ebb -> {
226                 logger.info(ebb.getBuildingBlock().getBpmnFlowName());
227                 flowNames.add(ebb.getBuildingBlock().getBpmnFlowName());
228             });
229
230             if (!isResume) {
231                 bbInputSetupUtils.persistFlowExecutionPath(requestId, flowsToExecute);
232             }
233             setExecutionVariables(execution, flowsToExecute, flowNames);
234
235         } catch (Exception ex) {
236             if (!(execution.hasVariable("WorkflowException")
237                     || execution.hasVariable("WorkflowExceptionExceptionMessage"))) {
238                 buildAndThrowException(execution, "Exception while setting execution list. ", ex);
239             } else {
240                 throw ex;
241             }
242         }
243     }
244
245     private List<ExecuteBuildingBlock> loadExecuteBuildingBlocksForAlaCarte(List<OrchestrationFlow> orchFlows,
246             DelegateExecution execution, String requestAction, WorkflowType resourceType, String cloudOwner,
247             String serviceType, ServiceInstancesRequest sIRequest, String requestId,
248             WorkflowResourceIds workflowResourceIds, RequestDetails requestDetails, String resourceId, String vnfType,
249             String apiVersion) throws Exception {
250         List<ExecuteBuildingBlock> flowsToExecute = new ArrayList<>();
251         if (orchFlows == null || orchFlows.isEmpty()) {
252             orchFlows = queryNorthBoundRequestCatalogDb(execution, requestAction, resourceType, true, cloudOwner,
253                     serviceType);
254         }
255         Resource resourceKey = getResourceKey(sIRequest, resourceType);
256
257         ReplaceInstanceRelatedInformation replaceInfo = new ReplaceInstanceRelatedInformation();
258         if ((requestAction.equalsIgnoreCase(REPLACEINSTANCE)
259                 || requestAction.equalsIgnoreCase(REPLACEINSTANCERETAINASSIGNMENTS))
260                 && resourceType.equals(WorkflowType.VFMODULE)) {
261             logger.debug("Build a BB list for replacing BB modules");
262             ConfigBuildingBlocksDataObject cbbdo = createConfigBuildingBlocksDataObject(execution, sIRequest, requestId,
263                     workflowResourceIds, requestDetails, requestAction, resourceId, vnfType, orchFlows, apiVersion,
264                     resourceKey, replaceInfo);
265             orchFlows = getVfModuleReplaceBuildingBlocks(cbbdo);
266
267             createBuildingBlocksForOrchFlows(execution, sIRequest, requestId, workflowResourceIds, requestDetails,
268                     requestAction, resourceId, flowsToExecute, vnfType, orchFlows, apiVersion, resourceKey,
269                     replaceInfo);
270         } else {
271             if (isConfiguration(orchFlows) && !requestAction.equalsIgnoreCase(CREATE_INSTANCE)) {
272                 addConfigBuildingBlocksToFlowsToExecuteList(execution, sIRequest, requestId, workflowResourceIds,
273                         requestDetails, requestAction, resourceId, flowsToExecute, vnfType, apiVersion, resourceKey,
274                         replaceInfo, orchFlows);
275             }
276             orchFlows = orchFlows.stream().filter(item -> !item.getFlowName().contains(FABRIC_CONFIGURATION))
277                     .collect(Collectors.toList());
278
279             for (OrchestrationFlow orchFlow : orchFlows) {
280                 ExecuteBuildingBlock ebb = executeBuildingBlockBuilder.buildExecuteBuildingBlock(orchFlow, requestId,
281                         resourceKey, apiVersion, resourceId, requestAction, true, vnfType, workflowResourceIds,
282                         requestDetails, false, null, null, false, replaceInfo);
283                 flowsToExecute.add(ebb);
284             }
285         }
286         return flowsToExecute;
287     }
288
289     private List<ExecuteBuildingBlock> loadExecuteBuildingBlocksForMacro(ServiceInstancesRequest sIRequest,
290             WorkflowType resourceType, String requestAction, DelegateExecution execution, String serviceInstanceId,
291             String resourceId, WorkflowResourceIds workflowResourceIds, List<OrchestrationFlow> orchFlows,
292             String cloudOwner, String serviceType, String requestId, String apiVersion, String vnfType,
293             RequestDetails requestDetails) throws IOException, VrfBondingServiceException {
294         List<ExecuteBuildingBlock> flowsToExecute;
295         boolean containsService = false;
296         List<Resource> resourceList = new ArrayList<>();
297         List<Pair<WorkflowType, String>> aaiResourceIds = new ArrayList<>();
298         List<Map<String, Object>> userParams = sIRequest.getRequestDetails().getRequestParameters().getUserParams();
299         if (resourceType == WorkflowType.SERVICE && requestAction.equalsIgnoreCase(ASSIGNINSTANCE)) {
300             // SERVICE-MACRO-ASSIGN will always get user params with a
301             // service.
302
303             if (userParams != null) {
304                 containsService = isContainsService(sIRequest);
305                 if (containsService) {
306                     resourceList = userParamsServiceTraversal.getResourceListFromUserParams(execution, userParams,
307                             serviceInstanceId, requestAction);
308                 }
309             } else {
310                 buildAndThrowException(execution,
311                         "Service-Macro-Assign request details must contain user params with a service");
312             }
313         } else if (resourceType == WorkflowType.SERVICE && requestAction.equalsIgnoreCase(CREATE_INSTANCE)) {
314             // SERVICE-MACRO-CREATE will get user params with a service,
315             // a service with a network, a service with a
316             // network collection, OR an empty service.
317             // If user params is just a service or null and macro
318             // queries the SI and finds a VNF, macro fails.
319
320             if (userParams != null) {
321                 containsService = isContainsService(sIRequest);
322             }
323             if (containsService) {
324                 resourceList = userParamsServiceTraversal.getResourceListFromUserParams(execution, userParams,
325                         serviceInstanceId, requestAction);
326             }
327             if (!foundRelated(resourceList)) {
328                 traverseCatalogDbService(execution, sIRequest, resourceList, aaiResourceIds);
329             }
330         } else if (resourceType == WorkflowType.SERVICE && ("activateInstance".equalsIgnoreCase(requestAction)
331                 || "unassignInstance".equalsIgnoreCase(requestAction)
332                 || "deleteInstance".equalsIgnoreCase(requestAction)
333                 || requestAction.equalsIgnoreCase("activate" + FABRIC_CONFIGURATION))) {
334             // SERVICE-MACRO-ACTIVATE, SERVICE-MACRO-UNASSIGN, and
335             // SERVICE-MACRO-DELETE
336             // Will never get user params with service, macro will have
337             // to query the SI in AAI to find related instances.
338             traverseAAIService(execution, resourceList, resourceId, aaiResourceIds);
339         } else if (resourceType == WorkflowType.SERVICE && "deactivateInstance".equalsIgnoreCase(requestAction)) {
340             resourceList.add(new Resource(WorkflowType.SERVICE, "", false));
341         } else if (resourceType == WorkflowType.VNF && (REPLACEINSTANCE.equalsIgnoreCase(requestAction)
342                 || ("recreateInstance".equalsIgnoreCase(requestAction)))) {
343             traverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
344                     workflowResourceIds.getVnfId(), aaiResourceIds);
345         } else if (resourceType == WorkflowType.VNF && "updateInstance".equalsIgnoreCase(requestAction)) {
346             customTraverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
347                     workflowResourceIds.getVnfId(), aaiResourceIds);
348         } else {
349             buildAndThrowException(execution, "Current Macro Request is not supported");
350         }
351         StringBuilder foundObjects = new StringBuilder();
352         for (WorkflowType type : WorkflowType.values()) {
353             foundObjects.append(type).append(" - ")
354                     .append((int) resourceList.stream().filter(x -> type.equals(x.getResourceType())).count())
355                     .append("    ");
356         }
357         logger.info("Found {}", foundObjects);
358
359         if (orchFlows == null || orchFlows.isEmpty()) {
360             orchFlows = queryNorthBoundRequestCatalogDb(execution, requestAction, resourceType, false, cloudOwner,
361                     serviceType);
362         }
363         boolean vnfReplace = false;
364         if (resourceType.equals(WorkflowType.VNF) && (REPLACEINSTANCE.equalsIgnoreCase(requestAction)
365                 || REPLACEINSTANCERETAINASSIGNMENTS.equalsIgnoreCase(requestAction))) {
366             vnfReplace = true;
367         }
368         flowsToExecute = executeBuildingBlockBuilder.buildExecuteBuildingBlockList(orchFlows, resourceList, requestId,
369                 apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails, vnfReplace);
370         if (isNetworkCollectionInTheResourceList(resourceList)) {
371             logger.info("Sorting for Vlan Tagging");
372             flowsToExecute = sortExecutionPathByObjectForVlanTagging(flowsToExecute, requestAction);
373         }
374         // By default, enable homing at VNF level for CREATE_INSTANCE and ASSIGNINSTANCE
375         if (resourceType == WorkflowType.SERVICE
376                 && (requestAction.equals(CREATE_INSTANCE) || requestAction.equals(ASSIGNINSTANCE))
377                 && resourceList.stream().anyMatch(x -> WorkflowType.VNF.equals(x.getResourceType()))) {
378             execution.setVariable(HOMING, true);
379             execution.setVariable("calledHoming", false);
380         }
381         if (resourceType == WorkflowType.SERVICE && (requestAction.equalsIgnoreCase(ASSIGNINSTANCE)
382                 || requestAction.equalsIgnoreCase(CREATE_INSTANCE))) {
383             generateResourceIds(flowsToExecute, resourceList, serviceInstanceId);
384         } else {
385             updateResourceIdsFromAAITraversal(flowsToExecute, resourceList, aaiResourceIds, serviceInstanceId);
386         }
387         return flowsToExecute;
388     }
389
390     private void setExecutionVariables(DelegateExecution execution, List<ExecuteBuildingBlock> flowsToExecute,
391             List<String> flowNames) {
392         execution.setVariable("flowNames", flowNames);
393         execution.setVariable(BBConstants.G_CURRENT_SEQUENCE, 0);
394         execution.setVariable("retryCount", 0);
395         execution.setVariable("isRollback", false);
396         execution.setVariable("flowsToExecute", flowsToExecute);
397         execution.setVariable("isRollbackComplete", false);
398     }
399
400     private boolean isContainsService(ServiceInstancesRequest sIRequest) {
401         boolean containsService;
402         List<Map<String, Object>> userParams = sIRequest.getRequestDetails().getRequestParameters().getUserParams();
403         containsService = userParams.stream().anyMatch(param -> param.containsKey(USER_PARAM_SERVICE));
404         return containsService;
405     }
406
407
408
409     private List<ExecuteBuildingBlock> loadExecuteBuildingBlocks(DelegateExecution execution, String requestId,
410             String errorMessage) {
411         List<ExecuteBuildingBlock> flowsToExecute;
412         flowsToExecute = bbInputSetupUtils.loadOriginalFlowExecutionPath(requestId);
413         if (flowsToExecute == null) {
414             buildAndThrowException(execution, errorMessage);
415         }
416         return flowsToExecute;
417     }
418
419     private ConfigBuildingBlocksDataObject createConfigBuildingBlocksDataObject(DelegateExecution execution,
420             ServiceInstancesRequest sIRequest, String requestId, WorkflowResourceIds workflowResourceIds,
421             RequestDetails requestDetails, String requestAction, String resourceId, String vnfType,
422             List<OrchestrationFlow> orchFlows, String apiVersion, Resource resourceKey,
423             ReplaceInstanceRelatedInformation replaceInfo) {
424
425         return new ConfigBuildingBlocksDataObject().setsIRequest(sIRequest).setOrchFlows(orchFlows)
426                 .setRequestId(requestId).setResourceKey(resourceKey).setApiVersion(apiVersion).setResourceId(resourceId)
427                 .setRequestAction(requestAction).setaLaCarte(true).setVnfType(vnfType)
428                 .setWorkflowResourceIds(workflowResourceIds).setRequestDetails(requestDetails).setExecution(execution)
429                 .setReplaceInformation(replaceInfo);
430     }
431
432     private void createBuildingBlocksForOrchFlows(DelegateExecution execution, ServiceInstancesRequest sIRequest,
433             String requestId, WorkflowResourceIds workflowResourceIds, RequestDetails requestDetails,
434             String requestAction, String resourceId, List<ExecuteBuildingBlock> flowsToExecute, String vnfType,
435             List<OrchestrationFlow> orchFlows, String apiVersion, Resource resourceKey,
436             ReplaceInstanceRelatedInformation replaceInfo) throws Exception {
437
438         for (OrchestrationFlow orchFlow : orchFlows) {
439             if (orchFlow.getFlowName().contains(CONFIGURATION)) {
440                 List<OrchestrationFlow> configOrchFlows = new ArrayList<>();
441                 configOrchFlows.add(orchFlow);
442                 addConfigBuildingBlocksToFlowsToExecuteList(execution, sIRequest, requestId, workflowResourceIds,
443                         requestDetails, requestAction, resourceId, flowsToExecute, vnfType, apiVersion, resourceKey,
444                         replaceInfo, configOrchFlows);
445             } else {
446                 ExecuteBuildingBlock ebb = executeBuildingBlockBuilder.buildExecuteBuildingBlock(orchFlow, requestId,
447                         resourceKey, apiVersion, resourceId, requestAction, true, vnfType, workflowResourceIds,
448                         requestDetails, false, null, null, false, replaceInfo);
449                 flowsToExecute.add(ebb);
450             }
451         }
452     }
453
454     private void addConfigBuildingBlocksToFlowsToExecuteList(DelegateExecution execution,
455             ServiceInstancesRequest sIRequest, String requestId, WorkflowResourceIds workflowResourceIds,
456             RequestDetails requestDetails, String requestAction, String resourceId,
457             List<ExecuteBuildingBlock> flowsToExecute, String vnfType, String apiVersion, Resource resourceKey,
458             ReplaceInstanceRelatedInformation replaceInfo, List<OrchestrationFlow> configOrchFlows) throws Exception {
459
460         ConfigBuildingBlocksDataObject cbbdo = createConfigBuildingBlocksDataObject(execution, sIRequest, requestId,
461                 workflowResourceIds, requestDetails, requestAction, resourceId, vnfType, configOrchFlows, apiVersion,
462                 resourceKey, replaceInfo);
463         List<ExecuteBuildingBlock> configBuildingBlocks = getConfigBuildingBlocks(cbbdo);
464         flowsToExecute.addAll(configBuildingBlocks);
465     }
466
467     private Resource getResourceKey(ServiceInstancesRequest sIRequest, WorkflowType resourceType) {
468         String resourceId = "";
469         ModelInfo modelInfo = sIRequest.getRequestDetails().getModelInfo();
470         if (modelInfo != null) {
471             if (modelInfo.getModelType().equals(ModelType.service)) {
472                 resourceId = modelInfo.getModelVersionId();
473             } else {
474                 resourceId = modelInfo.getModelCustomizationId();
475             }
476         }
477         return new Resource(resourceType, resourceId, true);
478     }
479
480     private String getCloudOwner(CloudConfiguration cloudConfiguration) {
481         if (cloudConfiguration != null && cloudConfiguration.getCloudOwner() != null) {
482             return cloudConfiguration.getCloudOwner();
483         }
484         logger.warn("cloud owner value not found in request details, it will be set as default");
485         return environment.getProperty(DEFAULT_CLOUD_OWNER);
486     }
487
488     protected <T> List<T> getRelatedResourcesInVfModule(String vnfId, String vfModuleId, Class<T> resultClass,
489             AAIObjectName name) {
490         List<T> vnfcs = new ArrayList<>();
491         AAIResourceUri uri =
492                 AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId).vfModule(vfModuleId));
493         AAIResultWrapper vfModuleResultsWrapper = bbInputSetupUtils.getAAIResourceDepthOne(uri);
494         Optional<Relationships> relationshipsOp = vfModuleResultsWrapper.getRelationships();
495         if (relationshipsOp.isEmpty()) {
496             logger.debug("No relationships were found for vfModule in AAI");
497         } else {
498             Relationships relationships = relationshipsOp.get();
499             List<AAIResultWrapper> vnfcResultWrappers = relationships.getByType(name);
500             for (AAIResultWrapper vnfcResultWrapper : vnfcResultWrappers) {
501                 Optional<T> vnfcOp = vnfcResultWrapper.asBean(resultClass);
502                 vnfcOp.ifPresent(vnfcs::add);
503             }
504         }
505         return vnfcs;
506     }
507
508     protected <T> T getRelatedResourcesInVnfc(Vnfc vnfc, Class<T> resultClass, AAIObjectName name)
509             throws VnfcMultipleRelationshipException {
510         T configuration = null;
511         AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().vnfc(vnfc.getVnfcName()));
512         AAIResultWrapper vnfcResultsWrapper = bbInputSetupUtils.getAAIResourceDepthOne(uri);
513         Optional<Relationships> relationshipsOp = vnfcResultsWrapper.getRelationships();
514         if (relationshipsOp.isEmpty()) {
515             logger.debug("No relationships were found for VNFC in AAI");
516         } else {
517             Relationships relationships = relationshipsOp.get();
518             List<AAIResultWrapper> configurationResultWrappers =
519                     this.getResultWrappersFromRelationships(relationships, name);
520             if (configurationResultWrappers.size() > 1) {
521                 throw new VnfcMultipleRelationshipException(vnfc.getVnfcName());
522             }
523             if (!configurationResultWrappers.isEmpty()) {
524                 Optional<T> configurationOp = configurationResultWrappers.get(0).asBean(resultClass);
525                 if (configurationOp.isPresent()) {
526                     configuration = configurationOp.get();
527                 }
528             }
529         }
530         return configuration;
531     }
532
533     protected List<AAIResultWrapper> getResultWrappersFromRelationships(Relationships relationships,
534             AAIObjectName name) {
535         return relationships.getByType(name);
536     }
537
538     protected boolean isConfiguration(List<OrchestrationFlow> orchFlows) {
539         for (OrchestrationFlow flow : orchFlows) {
540             if (flow.getFlowName().contains(CONFIGURATION) && !"ConfigurationScaleOutBB".equals(flow.getFlowName())) {
541                 return true;
542             }
543         }
544         return false;
545     }
546
547     protected List<ExecuteBuildingBlock> getConfigBuildingBlocks(ConfigBuildingBlocksDataObject dataObj)
548             throws AAIEntityNotFoundException, VnfcMultipleRelationshipException {
549
550         List<ExecuteBuildingBlock> flowsToExecuteConfigs = new ArrayList<>();
551         List<OrchestrationFlow> result = dataObj.getOrchFlows().stream()
552                 .filter(item -> item.getFlowName().contains(FABRIC_CONFIGURATION)).collect(Collectors.toList());
553         String vnfId = dataObj.getWorkflowResourceIds().getVnfId();
554         String vfModuleId = dataObj.getWorkflowResourceIds().getVfModuleId();
555
556         String vnfCustomizationUUID = bbInputSetupUtils.getAAIGenericVnf(vnfId).getModelCustomizationId();
557         String vfModuleCustomizationUUID;
558         org.onap.aai.domain.yang.VfModule aaiVfModule = bbInputSetupUtils.getAAIVfModule(vnfId, vfModuleId);
559
560         if (aaiVfModule == null) {
561             logger.error("No matching VfModule is found in Generic-Vnf in AAI for vnfId: {} and vfModuleId : {}", vnfId,
562                     vfModuleId);
563             throw new AAIEntityNotFoundException("No matching VfModule is found in Generic-Vnf in AAI for vnfId: "
564                     + vnfId + " and vfModuleId : " + vfModuleId);
565         } else {
566             vfModuleCustomizationUUID = aaiVfModule.getModelCustomizationId();
567         }
568         String replaceVfModuleCustomizationUUID = "";
569         String replaceVnfModuleCustomizationUUID = "";
570         boolean isReplace = false;
571         if (dataObj.getRequestAction().equalsIgnoreCase("replaceInstance")
572                 || dataObj.getRequestAction().equalsIgnoreCase("replaceInstanceRetainAssignments")) {
573             for (RelatedInstanceList relatedInstList : dataObj.getRequestDetails().getRelatedInstanceList()) {
574                 RelatedInstance relatedInstance = relatedInstList.getRelatedInstance();
575                 if (relatedInstance.getModelInfo().getModelType().equals(ModelType.vnf)) {
576                     replaceVnfModuleCustomizationUUID = relatedInstance.getModelInfo().getModelCustomizationId();
577                 }
578             }
579             replaceVfModuleCustomizationUUID = dataObj.getRequestDetails().getModelInfo().getModelCustomizationId();
580             isReplace = true;
581         }
582
583         List<org.onap.aai.domain.yang.Vnfc> vnfcs =
584                 getRelatedResourcesInVfModule(vnfId, vfModuleId, org.onap.aai.domain.yang.Vnfc.class, Types.VNFC);
585         for (org.onap.aai.domain.yang.Vnfc vnfc : vnfcs) {
586             WorkflowResourceIds workflowIdsCopy = SerializationUtils.clone(dataObj.getWorkflowResourceIds());
587             org.onap.aai.domain.yang.Configuration configuration =
588                     getRelatedResourcesInVnfc(vnfc, org.onap.aai.domain.yang.Configuration.class, Types.CONFIGURATION);
589             if (configuration == null) {
590                 logger.warn(String.format("No configuration found for VNFC %s in AAI", vnfc.getVnfcName()));
591                 continue;
592             }
593             workflowIdsCopy.setConfigurationId(configuration.getConfigurationId());
594             for (OrchestrationFlow orchFlow : result) {
595                 if (!isReplace || (isReplace && (orchFlow.getFlowName().contains("Delete")))) {
596                     if (!isReplace) {
597                         dataObj.getResourceKey().setVfModuleCustomizationId(vfModuleCustomizationUUID);
598                         dataObj.getResourceKey().setVnfCustomizationId(vnfCustomizationUUID);
599                     } else {
600                         if (orchFlow.getFlowName().contains("Delete")) {
601                             dataObj.getResourceKey().setVfModuleCustomizationId(vfModuleCustomizationUUID);
602                             dataObj.getResourceKey().setVnfCustomizationId(vnfCustomizationUUID);
603                         } else {
604                             dataObj.getResourceKey().setVfModuleCustomizationId(replaceVfModuleCustomizationUUID);
605                             dataObj.getResourceKey().setVnfCustomizationId(replaceVnfModuleCustomizationUUID);
606                         }
607                     }
608                     dataObj.getResourceKey().setCvnfModuleCustomizationId(vnfc.getModelCustomizationId());
609                     String vnfcName = vnfc.getVnfcName();
610                     if (vnfcName == null || vnfcName.isEmpty()) {
611                         buildAndThrowException(dataObj.getExecution(), "Exception in create execution list "
612                                 + ": VnfcName does not exist or is null while there is a configuration for the vfModule",
613                                 new Exception("Vnfc and Configuration do not match"));
614                     }
615                     ExecuteBuildingBlock ebb =
616                             executeBuildingBlockBuilder.buildExecuteBuildingBlock(orchFlow, dataObj.getRequestId(),
617                                     dataObj.getResourceKey(), dataObj.getApiVersion(), dataObj.getResourceId(),
618                                     dataObj.getRequestAction(), dataObj.isaLaCarte(), dataObj.getVnfType(),
619                                     workflowIdsCopy, dataObj.getRequestDetails(), false, null, vnfcName, true, null);
620                     flowsToExecuteConfigs.add(ebb);
621                 }
622             }
623         }
624         return flowsToExecuteConfigs;
625     }
626
627     protected void buildAndThrowException(DelegateExecution execution, String msg) {
628         logger.error(msg);
629         execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, msg);
630         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg);
631     }
632
633     protected void buildAndThrowException(DelegateExecution execution, String msg, Exception ex) {
634         logger.error(msg, ex);
635         execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, msg + ex.getMessage());
636         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg + ex.getMessage());
637     }
638
639     protected List<OrchestrationFlow> getVfModuleReplaceBuildingBlocks(ConfigBuildingBlocksDataObject dataObj)
640             throws Exception {
641
642         String vnfId = dataObj.getWorkflowResourceIds().getVnfId();
643         String vfModuleId = dataObj.getWorkflowResourceIds().getVfModuleId();
644
645         logger.debug("BUILDING REPLACE LIST");
646
647         boolean volumeGroupExisted = false;
648         boolean volumeGroupWillExist = false;
649         boolean keepVolumeGroup = false;
650
651         boolean rebuildVolumeGroups = false;
652         if (dataObj.getRequestDetails().getRequestParameters() != null
653                 && dataObj.getRequestDetails().getRequestParameters().getRebuildVolumeGroups() != null) {
654             rebuildVolumeGroups = dataObj.getRequestDetails().getRequestParameters().getRebuildVolumeGroups();
655         }
656         String volumeGroupName = "";
657         Optional<VolumeGroup> volumeGroupFromVfModule =
658                 bbInputSetupUtils.getRelatedVolumeGroupFromVfModule(vnfId, vfModuleId);
659         if (volumeGroupFromVfModule.isPresent()) {
660             String volumeGroupId = volumeGroupFromVfModule.get().getVolumeGroupId();
661             volumeGroupName = volumeGroupFromVfModule.get().getVolumeGroupName();
662             logger.debug("Volume group id of the existing volume group is: {}", volumeGroupId);
663             volumeGroupExisted = true;
664             dataObj.getWorkflowResourceIds().setVolumeGroupId(volumeGroupId);
665             dataObj.getReplaceInformation().setOldVolumeGroupName(volumeGroupName);
666         }
667
668         List<OrchestrationFlow> orchFlows = dataObj.getOrchFlows();
669         VfModuleCustomization vfModuleCustomization = catalogDbClient.getVfModuleCustomizationByModelCuztomizationUUID(
670                 dataObj.getRequestDetails().getModelInfo().getModelCustomizationUuid());
671         if (vfModuleCustomization != null && vfModuleCustomization.getVfModule() != null
672                 && vfModuleCustomization.getVfModule().getVolumeHeatTemplate() != null
673                 && vfModuleCustomization.getVolumeHeatEnv() != null) {
674             volumeGroupWillExist = true;
675             if (!volumeGroupExisted) {
676                 String newVolumeGroupId = UUID.randomUUID().toString();
677                 dataObj.getWorkflowResourceIds().setVolumeGroupId(newVolumeGroupId);
678                 dataObj.getReplaceInformation().setOldVolumeGroupName(volumeGroupName);
679                 logger.debug("newVolumeGroupId: {}", newVolumeGroupId);
680             }
681         }
682
683         if (volumeGroupExisted && volumeGroupWillExist && !rebuildVolumeGroups) {
684             keepVolumeGroup = true;
685         }
686
687         if (!volumeGroupExisted || keepVolumeGroup) {
688             logger.debug("Filtering out deletion of volume groups");
689             orchFlows = orchFlows.stream().filter(item -> !item.getFlowName().matches(VOLUMEGROUP_DELETE_PATTERN))
690                     .collect(Collectors.toList());
691         }
692         if (!volumeGroupWillExist || keepVolumeGroup) {
693             logger.debug("Filtering out creation of volume groups");
694             orchFlows = orchFlows.stream().filter(item -> !item.getFlowName().matches(VOLUMEGROUP_CREATE_PATTERN))
695                     .collect(Collectors.toList());
696         }
697
698         return orchFlows;
699     }
700
701
702
703     private void updateResourceIdsFromAAITraversal(List<ExecuteBuildingBlock> flowsToExecute,
704             List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds, String serviceInstanceId) {
705         for (Pair<WorkflowType, String> pair : aaiResourceIds) {
706             logger.debug("{}, {}", pair.getValue0(), pair.getValue1());
707         }
708
709         Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE))
710                 .forEach(type -> resourceList.stream().filter(resource -> type.equals(resource.getResourceType()))
711                         .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource.getResourceId(),
712                                 retrieveAAIResourceId(aaiResourceIds, type), null, serviceInstanceId)));
713     }
714
715     private String retrieveAAIResourceId(List<Pair<WorkflowType, String>> aaiResourceIds, WorkflowType resource) {
716         String id = null;
717         for (int i = 0; i < aaiResourceIds.size(); i++) {
718             if (aaiResourceIds.get(i).getValue0() == resource) {
719                 id = aaiResourceIds.get(i).getValue1();
720                 aaiResourceIds.remove(i);
721                 break;
722             }
723         }
724         return id;
725     }
726
727     private void generateResourceIds(List<ExecuteBuildingBlock> flowsToExecute, List<Resource> resourceList,
728             String serviceInstanceId) {
729         Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE))
730                 .forEach(type -> resourceList.stream().filter(resource -> type.equals(resource.getResourceType()))
731                         .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource.getResourceId(),
732                                 null, resource.getVirtualLinkKey(), serviceInstanceId)));
733     }
734
735     protected void updateWorkflowResourceIds(List<ExecuteBuildingBlock> flowsToExecute, WorkflowType resourceType,
736             String key, String id, String virtualLinkKey, String serviceInstanceId) {
737         String resourceId = id;
738         if (resourceId == null) {
739             resourceId = UUID.randomUUID().toString();
740         }
741         for (ExecuteBuildingBlock ebb : flowsToExecute) {
742             if (key != null && key.equalsIgnoreCase(ebb.getBuildingBlock().getKey()) && (ebb.getBuildingBlock()
743                     .getBpmnFlowName().contains(resourceType.toString())
744                     || (ebb.getBuildingBlock().getBpmnFlowName().contains(CONTROLLER)
745                             && ebb.getBuildingBlock().getBpmnScope().equalsIgnoreCase(resourceType.toString())))) {
746                 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
747                 workflowResourceIds.setServiceInstanceId(serviceInstanceId);
748                 WorkflowResourceIdsUtils.setResourceIdByWorkflowType(workflowResourceIds, resourceType, resourceId);
749                 ebb.setWorkflowResourceIds(workflowResourceIds);
750             }
751             if (virtualLinkKey != null && ebb.getBuildingBlock().isVirtualLink()
752                     && virtualLinkKey.equalsIgnoreCase(ebb.getBuildingBlock().getVirtualLinkKey())) {
753                 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
754                 workflowResourceIds.setServiceInstanceId(serviceInstanceId);
755                 workflowResourceIds.setNetworkId(resourceId);
756                 ebb.setWorkflowResourceIds(workflowResourceIds);
757             }
758         }
759     }
760
761     protected CollectionResourceCustomization findCatalogNetworkCollection(DelegateExecution execution,
762             org.onap.so.db.catalog.beans.Service service) {
763         CollectionResourceCustomization networkCollection = null;
764         int count = 0;
765         for (CollectionResourceCustomization collectionCust : service.getCollectionResourceCustomizations()) {
766             if (catalogDbClient.getNetworkCollectionResourceCustomizationByID(
767                     collectionCust.getModelCustomizationUUID()) != null) {
768                 networkCollection = collectionCust;
769                 count++;
770             }
771         }
772         if (count == 0) {
773             return null;
774         } else if (count > 1) {
775             buildAndThrowException(execution,
776                     "Found multiple Network Collections in the Service model, only one per Service is supported.");
777         }
778         return networkCollection;
779     }
780
781     protected void traverseCatalogDbService(DelegateExecution execution, ServiceInstancesRequest sIRequest,
782             List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds)
783             throws JsonProcessingException, VrfBondingServiceException {
784         String modelUUID = sIRequest.getRequestDetails().getModelInfo().getModelVersionId();
785         org.onap.so.db.catalog.beans.Service service = catalogDbClient.getServiceByID(modelUUID);
786
787         if (service == null) {
788             buildAndThrowException(execution, "Could not find the service model in catalog db.");
789         } else {
790             resourceList.add(new Resource(WorkflowType.SERVICE, service.getModelUUID(), false));
791             RelatedInstance relatedVpnBinding =
792                     bbInputSetupUtils.getRelatedInstanceByType(sIRequest.getRequestDetails(), ModelType.vpnBinding);
793             RelatedInstance relatedLocalNetwork =
794                     bbInputSetupUtils.getRelatedInstanceByType(sIRequest.getRequestDetails(), ModelType.network);
795
796             if (relatedVpnBinding != null && relatedLocalNetwork != null) {
797                 traverseVrfConfiguration(aaiResourceIds, resourceList, service, relatedVpnBinding, relatedLocalNetwork);
798             } else {
799                 traverseNetworkCollection(execution, resourceList, service);
800             }
801         }
802     }
803
804     protected void traverseVrfConfiguration(List<Pair<WorkflowType, String>> aaiResourceIds,
805             List<Resource> resourceList, org.onap.so.db.catalog.beans.Service service,
806             RelatedInstance relatedVpnBinding, RelatedInstance relatedLocalNetwork)
807             throws VrfBondingServiceException, JsonProcessingException {
808         org.onap.aai.domain.yang.L3Network aaiLocalNetwork =
809                 bbInputSetupUtils.getAAIL3Network(relatedLocalNetwork.getInstanceId());
810         vrfValidation.vrfServiceValidation(service);
811         vrfValidation.vrfCatalogDbChecks(service);
812         vrfValidation.aaiVpnBindingValidation(relatedVpnBinding.getInstanceId(),
813                 bbInputSetupUtils.getAAIVpnBinding(relatedVpnBinding.getInstanceId()));
814         vrfValidation.aaiNetworkValidation(relatedLocalNetwork.getInstanceId(), aaiLocalNetwork);
815         vrfValidation.aaiSubnetValidation(aaiLocalNetwork);
816         vrfValidation.aaiAggregateRouteValidation(aaiLocalNetwork);
817         vrfValidation.aaiRouteTargetValidation(aaiLocalNetwork);
818         String existingAAIVrfConfiguration = getExistingAAIVrfConfiguration(relatedVpnBinding, aaiLocalNetwork);
819         if (existingAAIVrfConfiguration != null) {
820             aaiResourceIds.add(new Pair<>(WorkflowType.CONFIGURATION, existingAAIVrfConfiguration));
821         }
822         resourceList.add(new Resource(WorkflowType.CONFIGURATION,
823                 service.getConfigurationCustomizations().get(0).getModelCustomizationUUID(), false));
824
825     }
826
827     protected String getExistingAAIVrfConfiguration(RelatedInstance relatedVpnBinding,
828             org.onap.aai.domain.yang.L3Network aaiLocalNetwork)
829             throws JsonProcessingException, VrfBondingServiceException {
830         Optional<Relationships> relationshipsOp = new AAIResultWrapper(
831                 new AAICommonObjectMapperProvider().getMapper().writeValueAsString(aaiLocalNetwork)).getRelationships();
832         if (relationshipsOp.isPresent()) {
833             List<AAIResultWrapper> configurationsRelatedToLocalNetwork =
834                     relationshipsOp.get().getByType(Types.CONFIGURATION);
835             if (configurationsRelatedToLocalNetwork.size() > 1) {
836                 throw new VrfBondingServiceException(
837                         "Network: " + aaiLocalNetwork.getNetworkId() + " has more than 1 configuration related to it");
838             }
839             if (configurationsRelatedToLocalNetwork.size() == 1) {
840                 AAIResultWrapper configWrapper = configurationsRelatedToLocalNetwork.get(0);
841                 Optional<Configuration> relatedConfiguration = configWrapper.asBean(Configuration.class);
842                 if (relatedConfiguration.isPresent() && vrfConfigurationAlreadyExists(relatedVpnBinding,
843                         relatedConfiguration.get(), configWrapper)) {
844                     return relatedConfiguration.get().getConfigurationId();
845                 }
846             }
847         }
848         return null;
849     }
850
851     protected boolean vrfConfigurationAlreadyExists(RelatedInstance relatedVpnBinding, Configuration vrfConfiguration,
852             AAIResultWrapper configWrapper) throws VrfBondingServiceException {
853         if ("VRF-ENTRY".equalsIgnoreCase(vrfConfiguration.getConfigurationType())) {
854             Optional<Relationships> relationshipsConfigOp = configWrapper.getRelationships();
855             if (relationshipsConfigOp.isPresent()) {
856                 Optional<VpnBinding> relatedInfraVpnBindingOp =
857                         workflowActionUtils.extractRelationshipsVpnBinding(relationshipsConfigOp.get());
858                 if (relatedInfraVpnBindingOp.isPresent()) {
859                     VpnBinding relatedInfraVpnBinding = relatedInfraVpnBindingOp.get();
860                     if (!relatedInfraVpnBinding.getVpnId().equalsIgnoreCase(relatedVpnBinding.getInstanceId())) {
861                         throw new VrfBondingServiceException("Configuration: " + vrfConfiguration.getConfigurationId()
862                                 + " is not connected to the same vpn binding id provided in request: "
863                                 + relatedVpnBinding.getInstanceId());
864                     } else {
865                         return true;
866                     }
867                 }
868             }
869         }
870         return false;
871     }
872
873     protected void traverseNetworkCollection(DelegateExecution execution, List<Resource> resourceList,
874             org.onap.so.db.catalog.beans.Service service) {
875         if (isVnfCustomizationsInTheService(service)) {
876             buildAndThrowException(execution,
877                     "Cannot orchestrate Service-Macro-Create without user params with a vnf. Please update ASDC model for new macro orchestration support or add service_recipe records to route to old macro flows");
878         }
879         if (isPnfCustomizationsInTheService(service)) {
880             buildAndThrowException(execution,
881                     "Cannot orchestrate Service-Macro-Create without user params with a pnf. Please update ASDC model for new macro orchestration support or add service_recipe records to route to old macro flows");
882         }
883         List<CollectionResourceCustomization> customizations = service.getCollectionResourceCustomizations();
884         if (customizations.isEmpty()) {
885             logger.debug("No Collections found. CollectionResourceCustomization list is empty.");
886         } else {
887             CollectionResourceCustomization collectionResourceCustomization =
888                     findCatalogNetworkCollection(execution, service);
889             traverseNetworkCollectionResourceCustomization(resourceList, collectionResourceCustomization);
890         }
891         traverseNetworkCollectionCustomization(resourceList, service);
892     }
893
894     private void traverseNetworkCollectionResourceCustomization(List<Resource> resourceList,
895             CollectionResourceCustomization collectionResourceCustomization) {
896         if (collectionResourceCustomizationShouldNotBeProcessed(resourceList, collectionResourceCustomization))
897             return;
898         int minNetworks = 0;
899         org.onap.so.db.catalog.beans.InstanceGroup instanceGroup =
900                 collectionResourceCustomization.getCollectionResource().getInstanceGroup();
901         CollectionResourceInstanceGroupCustomization collectionInstCust = null;
902         if (!instanceGroup.getCollectionInstanceGroupCustomizations().isEmpty()) {
903             for (CollectionResourceInstanceGroupCustomization collectionInstanceGroupTemp : instanceGroup
904                     .getCollectionInstanceGroupCustomizations()) {
905                 if (collectionInstanceGroupTemp.getModelCustomizationUUID()
906                         .equalsIgnoreCase(collectionResourceCustomization.getModelCustomizationUUID())) {
907                     collectionInstCust = collectionInstanceGroupTemp;
908                     break;
909                 }
910             }
911             if (interfaceNetworkQuantityIsAvailableInCollection(collectionInstCust)) {
912                 minNetworks = collectionInstCust.getSubInterfaceNetworkQuantity();
913             }
914         }
915         logger.debug("minNetworks: {}", minNetworks);
916         CollectionNetworkResourceCustomization collectionNetworkResourceCust =
917                 getCollectionNetworkResourceCustomization(collectionResourceCustomization, instanceGroup);
918         for (int i = 0; i < minNetworks; i++) {
919             if (collectionNetworkResourceCust != null) {
920                 Resource resource = new Resource(WorkflowType.VIRTUAL_LINK,
921                         collectionNetworkResourceCust.getModelCustomizationUUID(), false);
922                 resource.setVirtualLinkKey(Integer.toString(i));
923                 resourceList.add(resource);
924             }
925         }
926     }
927
928     private CollectionNetworkResourceCustomization getCollectionNetworkResourceCustomization(
929             CollectionResourceCustomization collectionResourceCustomization, InstanceGroup instanceGroup) {
930         CollectionNetworkResourceCustomization collectionNetworkResourceCust = null;
931         for (CollectionNetworkResourceCustomization collectionNetworkTemp : instanceGroup
932                 .getCollectionNetworkResourceCustomizations()) {
933             if (collectionNetworkTemp.getNetworkResourceCustomization().getModelCustomizationUUID()
934                     .equalsIgnoreCase(collectionResourceCustomization.getModelCustomizationUUID())) {
935                 collectionNetworkResourceCust = collectionNetworkTemp;
936                 break;
937             }
938         }
939         return collectionNetworkResourceCust;
940     }
941
942     private boolean collectionResourceCustomizationShouldNotBeProcessed(List<Resource> resourceList,
943             CollectionResourceCustomization collectionResourceCustomization) {
944         if (collectionResourceCustomization == null) {
945             logger.debug("No Network Collection Customization found");
946             return true;
947         }
948         resourceList.add(new Resource(WorkflowType.NETWORKCOLLECTION,
949                 collectionResourceCustomization.getModelCustomizationUUID(), false));
950         logger.debug("Found a network collection");
951         if (collectionResourceCustomization.getCollectionResource() == null) {
952             logger.debug("No Network Collection found. collectionResource is null");
953             return true;
954         }
955         if (collectionResourceCustomization.getCollectionResource().getInstanceGroup() == null) {
956             logger.debug("No Instance Group found for network collection.");
957             return true;
958         }
959         String toscaNodeType =
960                 collectionResourceCustomization.getCollectionResource().getInstanceGroup().getToscaNodeType();
961         if (!toscaNodeTypeHasNetworkCollection(toscaNodeType)) {
962             logger.debug("Instance Group tosca node type does not contain NetworkCollection:  {}", toscaNodeType);
963             return true;
964         }
965         return false;
966     }
967
968     private boolean interfaceNetworkQuantityIsAvailableInCollection(
969             CollectionResourceInstanceGroupCustomization collectionInstCust) {
970         return collectionInstCust != null && collectionInstCust.getSubInterfaceNetworkQuantity() != null;
971     }
972
973     private boolean toscaNodeTypeHasNetworkCollection(String toscaNodeType) {
974         return toscaNodeType != null && toscaNodeType.contains(NETWORKCOLLECTION);
975     }
976
977     private void traverseNetworkCollectionCustomization(List<Resource> resourceList,
978             org.onap.so.db.catalog.beans.Service service) {
979         if (isNetworkCollectionInTheResourceList(resourceList)) {
980             return;
981         }
982         if (service.getNetworkCustomizations() == null) {
983             logger.debug("No networks were found on this service model");
984             return;
985         }
986         for (int i = 0; i < service.getNetworkCustomizations().size(); i++) {
987             resourceList.add(new Resource(WorkflowType.NETWORK,
988                     service.getNetworkCustomizations().get(i).getModelCustomizationUUID(), false));
989         }
990     }
991
992     private boolean isNetworkCollectionInTheResourceList(List<Resource> resourceList) {
993         return resourceList.stream().anyMatch(x -> WorkflowType.NETWORKCOLLECTION == x.getResourceType());
994     }
995
996     private boolean isVnfCustomizationsInTheService(org.onap.so.db.catalog.beans.Service service) {
997         return !(service.getVnfCustomizations() == null || service.getVnfCustomizations().isEmpty());
998     }
999
1000     private boolean isPnfCustomizationsInTheService(org.onap.so.db.catalog.beans.Service service) {
1001         return !(service.getPnfCustomizations() == null || service.getPnfCustomizations().isEmpty());
1002     }
1003
1004     protected void traverseAAIService(DelegateExecution execution, List<Resource> resourceList, String resourceId,
1005             List<Pair<WorkflowType, String>> aaiResourceIds) {
1006         try {
1007             ServiceInstance serviceInstanceAAI = bbInputSetupUtils.getAAIServiceInstanceById(resourceId);
1008             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO =
1009                     bbInputSetup.getExistingServiceInstance(serviceInstanceAAI);
1010             resourceList.add(new Resource(WorkflowType.SERVICE, serviceInstanceMSO.getServiceInstanceId(), false));
1011             traverseServiceInstanceMSOVnfs(resourceList, aaiResourceIds, serviceInstanceMSO);
1012             traverseServiceInstanceMSOPnfs(resourceList, aaiResourceIds, serviceInstanceMSO);
1013             if (serviceInstanceMSO.getNetworks() != null) {
1014                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.L3Network network : serviceInstanceMSO
1015                         .getNetworks()) {
1016                     aaiResourceIds.add(new Pair<>(WorkflowType.NETWORK, network.getNetworkId()));
1017                     resourceList.add(new Resource(WorkflowType.NETWORK, network.getNetworkId(), false));
1018                 }
1019             }
1020             if (serviceInstanceMSO.getCollection() != null) {
1021                 logger.debug("found networkcollection");
1022                 aaiResourceIds
1023                         .add(new Pair<>(WorkflowType.NETWORKCOLLECTION, serviceInstanceMSO.getCollection().getId()));
1024                 resourceList.add(new Resource(WorkflowType.NETWORKCOLLECTION,
1025                         serviceInstanceMSO.getCollection().getId(), false));
1026             }
1027             if (serviceInstanceMSO.getConfigurations() != null) {
1028                 for (Configuration config : serviceInstanceMSO.getConfigurations()) {
1029                     Optional<org.onap.aai.domain.yang.Configuration> aaiConfig =
1030                             aaiConfigurationResources.getConfiguration(config.getConfigurationId());
1031                     if (aaiConfig.isPresent() && aaiConfig.get().getRelationshipList() != null) {
1032                         for (Relationship relationship : aaiConfig.get().getRelationshipList().getRelationship()) {
1033                             if (relationship.getRelatedTo().contains("vnfc")
1034                                     || relationship.getRelatedTo().contains("vpn-binding")) {
1035                                 aaiResourceIds.add(new Pair<>(WorkflowType.CONFIGURATION, config.getConfigurationId()));
1036                                 resourceList.add(
1037                                         new Resource(WorkflowType.CONFIGURATION, config.getConfigurationId(), false));
1038                                 break;
1039                             }
1040                         }
1041                     }
1042                 }
1043             }
1044         } catch (Exception ex) {
1045             logger.error("Exception in traverseAAIService", ex);
1046             buildAndThrowException(execution,
1047                     "Could not find existing Service Instance or related Instances to execute the request on.");
1048         }
1049     }
1050
1051     private void traverseServiceInstanceMSOVnfs(List<Resource> resourceList,
1052             List<Pair<WorkflowType, String>> aaiResourceIds,
1053             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO) {
1054         if (serviceInstanceMSO.getVnfs() == null) {
1055             return;
1056         }
1057         for (org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf : serviceInstanceMSO.getVnfs()) {
1058             aaiResourceIds.add(new Pair<>(WorkflowType.VNF, vnf.getVnfId()));
1059             resourceList.add(new Resource(WorkflowType.VNF, vnf.getVnfId(), false));
1060             traverseVnfModules(resourceList, aaiResourceIds, vnf);
1061             if (vnf.getVolumeGroups() != null) {
1062                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup volumeGroup : vnf.getVolumeGroups()) {
1063                     aaiResourceIds.add(new Pair<>(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId()));
1064                     resourceList.add(new Resource(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId(), false));
1065                 }
1066             }
1067         }
1068     }
1069
1070     private void traverseServiceInstanceMSOPnfs(List<Resource> resourceList,
1071             List<Pair<WorkflowType, String>> aaiResourceIds,
1072             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO) {
1073         if (serviceInstanceMSO.getPnfs() == null) {
1074             return;
1075         }
1076         for (org.onap.so.bpmn.servicedecomposition.bbobjects.Pnf pnf : serviceInstanceMSO.getPnfs()) {
1077             aaiResourceIds.add(new Pair<>(WorkflowType.PNF, pnf.getPnfId()));
1078             resourceList.add(new Resource(WorkflowType.PNF, pnf.getPnfId(), false));
1079         }
1080     }
1081
1082     private void traverseVnfModules(List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds,
1083             org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf) {
1084         if (vnf.getVfModules() == null) {
1085             return;
1086         }
1087         for (VfModule vfModule : vnf.getVfModules()) {
1088             aaiResourceIds.add(new Pair<>(WorkflowType.VFMODULE, vfModule.getVfModuleId()));
1089             Resource resource = new Resource(WorkflowType.VFMODULE, vfModule.getVfModuleId(), false);
1090             resource.setBaseVfModule(vfModule.getModelInfoVfModule().getIsBaseBoolean());
1091             resourceList.add(resource);
1092         }
1093     }
1094
1095     private void traverseAAIVnf(DelegateExecution execution, List<Resource> resourceList, String serviceId,
1096             String vnfId, List<Pair<WorkflowType, String>> aaiResourceIds) {
1097         try {
1098             ServiceInstance serviceInstanceAAI = bbInputSetupUtils.getAAIServiceInstanceById(serviceId);
1099             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO =
1100                     bbInputSetup.getExistingServiceInstance(serviceInstanceAAI);
1101             resourceList.add(new Resource(WorkflowType.SERVICE, serviceInstanceMSO.getServiceInstanceId(), false));
1102             if (serviceInstanceMSO.getVnfs() != null) {
1103                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf : serviceInstanceMSO.getVnfs()) {
1104                     if (vnf.getVnfId().equals(vnfId)) {
1105                         aaiResourceIds.add(new Pair<>(WorkflowType.VNF, vnf.getVnfId()));
1106                         resourceList.add(new Resource(WorkflowType.VNF, vnf.getVnfId(), false));
1107                         if (vnf.getVfModules() != null) {
1108                             for (VfModule vfModule : vnf.getVfModules()) {
1109                                 aaiResourceIds.add(new Pair<>(WorkflowType.VFMODULE, vfModule.getVfModuleId()));
1110                                 resourceList.add(new Resource(WorkflowType.VFMODULE, vfModule.getVfModuleId(), false));
1111                                 findConfigurationsInsideVfModule(execution, vnf.getVnfId(), vfModule.getVfModuleId(),
1112                                         resourceList, aaiResourceIds);
1113                             }
1114                         }
1115                         if (vnf.getVolumeGroups() != null) {
1116                             for (org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup volumeGroup : vnf
1117                                     .getVolumeGroups()) {
1118                                 aaiResourceIds
1119                                         .add(new Pair<>(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId()));
1120                                 resourceList.add(
1121                                         new Resource(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId(), false));
1122                             }
1123                         }
1124                         break;
1125                     }
1126                 }
1127             }
1128         } catch (Exception ex) {
1129             logger.error("Exception in traverseAAIVnf", ex);
1130             buildAndThrowException(execution,
1131                     "Could not find existing Vnf or related Instances to execute the request on.");
1132         }
1133     }
1134
1135     private void customTraverseAAIVnf(DelegateExecution execution, List<Resource> resourceList, String serviceId,
1136             String vnfId, List<Pair<WorkflowType, String>> aaiResourceIds) {
1137         try {
1138             ServiceInstance serviceInstanceAAI = bbInputSetupUtils.getAAIServiceInstanceById(serviceId);
1139             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO =
1140                     bbInputSetup.getExistingServiceInstance(serviceInstanceAAI);
1141             resourceList.add(new Resource(WorkflowType.SERVICE, serviceInstanceMSO.getServiceInstanceId(), false));
1142             if (serviceInstanceMSO.getVnfs() != null) {
1143                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf : serviceInstanceMSO.getVnfs()) {
1144                     if (vnf.getVnfId().equals(vnfId)) {
1145                         aaiResourceIds.add(new Pair<>(WorkflowType.VNF, vnf.getVnfId()));
1146
1147                         String vnfCustomizationUUID =
1148                                 bbInputSetupUtils.getAAIGenericVnf(vnfId).getModelCustomizationId();
1149                         resourceList.add(new Resource(WorkflowType.VNF, vnfCustomizationUUID, false));
1150
1151                         if (vnf.getVfModules() != null) {
1152                             for (VfModule vfModule : vnf.getVfModules()) {
1153                                 aaiResourceIds.add(new Pair<>(WorkflowType.VFMODULE, vfModule.getVfModuleId()));
1154                                 resourceList.add(new Resource(WorkflowType.VFMODULE, vfModule.getVfModuleId(), false));
1155                                 findConfigurationsInsideVfModule(execution, vnf.getVnfId(), vfModule.getVfModuleId(),
1156                                         resourceList, aaiResourceIds);
1157                             }
1158                         }
1159                         if (vnf.getVolumeGroups() != null) {
1160                             for (org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup volumeGroup : vnf
1161                                     .getVolumeGroups()) {
1162                                 aaiResourceIds
1163                                         .add(new Pair<>(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId()));
1164                                 resourceList.add(
1165                                         new Resource(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId(), false));
1166                             }
1167                         }
1168                         break;
1169                     }
1170                 }
1171             }
1172         } catch (Exception ex) {
1173             logger.error("Exception in customTraverseAAIVnf", ex);
1174             buildAndThrowException(execution,
1175                     "Could not find existing Vnf or related Instances to execute the request on.");
1176         }
1177
1178     }
1179
1180     private void findConfigurationsInsideVfModule(DelegateExecution execution, String vnfId, String vfModuleId,
1181             List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds) {
1182         try {
1183             org.onap.aai.domain.yang.VfModule aaiVfModule = bbInputSetupUtils.getAAIVfModule(vnfId, vfModuleId);
1184             AAIResultWrapper vfModuleWrapper = new AAIResultWrapper(
1185                     new AAICommonObjectMapperProvider().getMapper().writeValueAsString(aaiVfModule));
1186             Optional<Relationships> relationshipsOp;
1187             relationshipsOp = vfModuleWrapper.getRelationships();
1188             if (relationshipsOp.isPresent()) {
1189                 relationshipsOp = workflowActionUtils.extractRelationshipsVnfc(relationshipsOp.get());
1190                 if (relationshipsOp.isPresent()) {
1191                     Optional<Configuration> config =
1192                             workflowActionUtils.extractRelationshipsConfiguration(relationshipsOp.get());
1193                     if (config.isPresent()) {
1194                         aaiResourceIds.add(new Pair<>(WorkflowType.CONFIGURATION, config.get().getConfigurationId()));
1195                         resourceList.add(
1196                                 new Resource(WorkflowType.CONFIGURATION, config.get().getConfigurationId(), false));
1197                     }
1198                 }
1199             }
1200         } catch (Exception ex) {
1201             logger.error("Exception in findConfigurationsInsideVfModule", ex);
1202             buildAndThrowException(execution, "Failed to find Configuration object from the vfModule.");
1203         }
1204     }
1205
1206     protected WorkflowResourceIds populateResourceIdsFromApiHandler(DelegateExecution execution) {
1207         return WorkflowResourceIdsUtils.getWorkflowResourceIdsFromExecution(execution);
1208     }
1209
1210     protected Resource extractResourceIdAndTypeFromUri(String uri) {
1211         Pattern patt = Pattern.compile("[vV]\\d+.*?(?:(?:/(?<type>" + SUPPORTEDTYPES
1212                 + ")(?:/(?<id>[^/]+))?)(?:/(?<action>[^/]+))?(?:/resume)?)?$");
1213         Matcher m = patt.matcher(uri);
1214         boolean generated = false;
1215
1216         if (m.find()) {
1217             logger.debug("found match on {} : {} ", uri, m);
1218             String type = m.group("type");
1219             String id = m.group("id");
1220             String action = m.group("action");
1221             if (type == null) {
1222                 throw new IllegalArgumentException("Uri could not be parsed. No type found. " + uri);
1223             }
1224             if (action == null) {
1225                 if (type.equals(SERVICE_INSTANCES) && (id == null || "assign".equals(id))) {
1226                     id = UUID.randomUUID().toString();
1227                     generated = true;
1228                 } else if (type.equals(VF_MODULES) && "scaleOut".equals(id)) {
1229                     id = UUID.randomUUID().toString();
1230                     generated = true;
1231                 }
1232             } else {
1233                 if (action.matches(SUPPORTEDTYPES)) {
1234                     id = UUID.randomUUID().toString();
1235                     generated = true;
1236                     type = action;
1237                 }
1238             }
1239             return new Resource(WorkflowType.fromString(convertTypeFromPlural(type)), id, generated);
1240         } else {
1241             throw new IllegalArgumentException("Uri could not be parsed: " + uri);
1242         }
1243     }
1244
1245     protected String convertTypeFromPlural(String type) {
1246         if (!type.matches(SUPPORTEDTYPES)) {
1247             return type;
1248         } else {
1249             if (type.equals(SERVICE_INSTANCES)) {
1250                 return SERVICE;
1251             } else {
1252                 return type.substring(0, 1).toUpperCase() + type.substring(1, type.length() - 1);
1253             }
1254         }
1255     }
1256
1257     protected List<ExecuteBuildingBlock> sortExecutionPathByObjectForVlanTagging(List<ExecuteBuildingBlock> orchFlows,
1258             String requestAction) {
1259         List<ExecuteBuildingBlock> sortedOrchFlows = new ArrayList<>();
1260         if (requestAction.equals(CREATE_INSTANCE)) {
1261             for (ExecuteBuildingBlock ebb : orchFlows) {
1262                 if (ebb.getBuildingBlock().getBpmnFlowName().equals("AssignNetworkBB")) {
1263                     String key = ebb.getBuildingBlock().getKey();
1264                     boolean isVirtualLink = Boolean.TRUE.equals(ebb.getBuildingBlock().isVirtualLink());
1265                     String virtualLinkKey = ebb.getBuildingBlock().getVirtualLinkKey();
1266                     sortedOrchFlows.add(ebb);
1267                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
1268                         if (!isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
1269                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
1270                             sortedOrchFlows.add(ebb2);
1271                             break;
1272                         }
1273                         if (isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
1274                                 && ebb2.getBuildingBlock().getVirtualLinkKey().equalsIgnoreCase(virtualLinkKey)) {
1275                             sortedOrchFlows.add(ebb2);
1276                             break;
1277                         }
1278                     }
1279                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
1280                         if (!isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)
1281                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
1282                             sortedOrchFlows.add(ebb2);
1283                             break;
1284                         }
1285                         if (isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)
1286                                 && ebb2.getBuildingBlock().getVirtualLinkKey().equalsIgnoreCase(virtualLinkKey)) {
1287                             sortedOrchFlows.add(ebb2);
1288                             break;
1289                         }
1290                     }
1291                 } else if (ebb.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
1292                         || ebb.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)) {
1293                     continue;
1294                 } else if (!"".equals(ebb.getBuildingBlock().getBpmnFlowName())) {
1295                     sortedOrchFlows.add(ebb);
1296                 }
1297             }
1298         } else if (requestAction.equals("deleteInstance")) {
1299             for (ExecuteBuildingBlock ebb : orchFlows) {
1300                 if (ebb.getBuildingBlock().getBpmnFlowName().equals("DeactivateNetworkBB")) {
1301                     sortedOrchFlows.add(ebb);
1302                     String key = ebb.getBuildingBlock().getKey();
1303                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
1304                         if (ebb2.getBuildingBlock().getBpmnFlowName().equals("DeleteNetworkBB")
1305                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
1306                             sortedOrchFlows.add(ebb2);
1307                             break;
1308                         }
1309                     }
1310                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
1311                         if (ebb2.getBuildingBlock().getBpmnFlowName().equals("UnassignNetworkBB")
1312                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
1313                             sortedOrchFlows.add(ebb2);
1314                             break;
1315                         }
1316                     }
1317                 } else if (ebb.getBuildingBlock().getBpmnFlowName().equals("DeleteNetworkBB")
1318                         || ebb.getBuildingBlock().getBpmnFlowName().equals("UnassignNetworkBB")) {
1319                     continue;
1320                 } else if (!ebb.getBuildingBlock().getBpmnFlowName().equals("")) {
1321                     sortedOrchFlows.add(ebb);
1322                 }
1323             }
1324         }
1325         return sortedOrchFlows;
1326     }
1327
1328     protected List<OrchestrationFlow> queryNorthBoundRequestCatalogDb(DelegateExecution execution, String requestAction,
1329             WorkflowType resourceName, boolean aLaCarte, String cloudOwner) {
1330         return this.queryNorthBoundRequestCatalogDb(execution, requestAction, resourceName, aLaCarte, cloudOwner, "");
1331     }
1332
1333     protected List<OrchestrationFlow> queryNorthBoundRequestCatalogDb(DelegateExecution execution, String requestAction,
1334             WorkflowType resourceName, boolean aLaCarte, String cloudOwner, String serviceType) {
1335         List<OrchestrationFlow> listToExecute = new ArrayList<>();
1336         NorthBoundRequest northBoundRequest;
1337         if (serviceType.equalsIgnoreCase(SERVICE_TYPE_TRANSPORT)
1338                 || serviceType.equalsIgnoreCase(SERVICE_TYPE_BONDING)) {
1339             northBoundRequest =
1340                     catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwnerAndServiceType(
1341                             requestAction, resourceName.toString(), aLaCarte, cloudOwner, serviceType);
1342         } else {
1343             northBoundRequest = catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwner(
1344                     requestAction, resourceName.toString(), aLaCarte, cloudOwner);
1345         }
1346         if (northBoundRequest == null) {
1347             northBoundRequest = catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwner(
1348                     requestAction, resourceName.toString(), aLaCarte, CLOUD_OWNER);
1349         }
1350         if (northBoundRequest == null) {
1351             buildAndThrowException(execution, String.format("The request: %s %s %s is not supported by GR_API.",
1352                     (aLaCarte ? "AlaCarte" : "Macro"), resourceName, requestAction));
1353         } else {
1354             if (northBoundRequest.getIsToplevelflow() != null) {
1355                 execution.setVariable(BBConstants.G_ISTOPLEVELFLOW, northBoundRequest.getIsToplevelflow());
1356             }
1357             List<OrchestrationFlow> flows = northBoundRequest.getOrchestrationFlowList();
1358             if (flows == null) {
1359                 flows = new ArrayList<>();
1360             } else {
1361                 flows.sort(Comparator.comparingInt(OrchestrationFlow::getSequenceNumber));
1362             }
1363             for (OrchestrationFlow flow : flows) {
1364                 if (!flow.getFlowName().contains("BB") && !flow.getFlowName().contains("Activity")) {
1365                     List<OrchestrationFlow> macroQueryFlows =
1366                             catalogDbClient.getOrchestrationFlowByAction(flow.getFlowName());
1367                     listToExecute.addAll(macroQueryFlows);
1368                 } else {
1369                     listToExecute.add(flow);
1370                 }
1371             }
1372         }
1373         return listToExecute;
1374     }
1375
1376     public void handleRuntimeException(DelegateExecution execution) {
1377         StringBuilder wfeExpMsg = new StringBuilder("Runtime error ");
1378         String runtimeErrorMessage;
1379         try {
1380             String javaExpMsg = (String) execution.getVariable("BPMN_javaExpMsg");
1381             if (javaExpMsg != null && !javaExpMsg.isEmpty()) {
1382                 wfeExpMsg.append(": ").append(javaExpMsg);
1383             }
1384             runtimeErrorMessage = wfeExpMsg.toString();
1385             logger.error(runtimeErrorMessage);
1386             execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, runtimeErrorMessage);
1387         } catch (Exception e) {
1388             logger.error("Runtime error", e);
1389             // if runtime message was mulformed
1390             runtimeErrorMessage = "Runtime error";
1391         }
1392         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, runtimeErrorMessage);
1393     }
1394
1395     protected boolean isUriResume(String uri) {
1396         return uri.endsWith("/resume");
1397     }
1398
1399     protected boolean isRequestMacroServiceResume(boolean aLaCarte, WorkflowType resourceType, String requestAction,
1400             String serviceInstanceId) {
1401         return (!aLaCarte && resourceType == WorkflowType.SERVICE
1402                 && (requestAction.equalsIgnoreCase(ASSIGNINSTANCE) || requestAction.equalsIgnoreCase(CREATE_INSTANCE))
1403                 && (serviceInstanceId != null && serviceInstanceId.trim().length() > 1)
1404                 && (bbInputSetupUtils.getAAIServiceInstanceById(serviceInstanceId) != null));
1405     }
1406
1407     protected boolean foundRelated(List<Resource> resourceList) {
1408         return (containsWorkflowType(resourceList, WorkflowType.VNF)
1409                 || containsWorkflowType(resourceList, WorkflowType.PNF)
1410                 || containsWorkflowType(resourceList, WorkflowType.NETWORK)
1411                 || containsWorkflowType(resourceList, WorkflowType.NETWORKCOLLECTION));
1412     }
1413
1414     protected boolean containsWorkflowType(List<Resource> resourceList, WorkflowType workflowType) {
1415         return resourceList.stream().anyMatch(resource -> resource.getResourceType().equals(workflowType));
1416     }
1417
1418     private void fillExecutionDefault(DelegateExecution execution) {
1419         execution.setVariable("sentSyncResponse", false);
1420         execution.setVariable(HOMING, false);
1421         execution.setVariable("calledHoming", false);
1422         execution.setVariable(BBConstants.G_ISTOPLEVELFLOW, true);
1423     }
1424
1425     private void fillExecution(DelegateExecution execution, boolean suppressRollback, String resourceId,
1426             WorkflowType resourceType) {
1427         execution.setVariable("suppressRollback", suppressRollback);
1428         execution.setVariable("resourceId", resourceId);
1429         execution.setVariable("resourceType", resourceType);
1430         execution.setVariable("resourceName", resourceType.toString());
1431     }
1432
1433     private Resource getResource(BBInputSetupUtils bbInputSetupUtils, boolean isResume, boolean alaCarte, String uri,
1434             String requestId) {
1435         if (!alaCarte && isResume) {
1436             logger.debug("replacing URI {}", uri);
1437             uri = bbInputSetupUtils.loadOriginalInfraActiveRequestById(requestId).getRequestUrl();
1438             logger.debug("for RESUME with original value {}", uri);
1439         }
1440         return extractResourceIdAndTypeFromUri(uri);
1441     }
1442
1443     private String getResourceId(Resource resource, String requestAction, RequestDetails requestDetails,
1444             WorkflowResourceIds workflowResourceIds) throws Exception {
1445         if (resource.isGenerated() && requestAction.equalsIgnoreCase("createInstance")
1446                 && requestDetails.getRequestInfo().getInstanceName() != null) {
1447             return aaiResourceIdValidator.validateResourceIdInAAI(resource.getResourceId(), resource.getResourceType(),
1448                     requestDetails.getRequestInfo().getInstanceName(), requestDetails, workflowResourceIds);
1449         } else {
1450             return resource.getResourceId();
1451         }
1452     }
1453
1454     private String getServiceInstanceId(DelegateExecution execution, String resourceId, WorkflowType resourceType) {
1455         String serviceInstanceId = (String) execution.getVariable("serviceInstanceId");
1456         if ((serviceInstanceId == null || serviceInstanceId.isEmpty()) && WorkflowType.SERVICE.equals(resourceType)) {
1457             serviceInstanceId = resourceId;
1458         }
1459         return serviceInstanceId;
1460     }
1461
1462 }