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