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