only add config create after activate is done
[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 || (isReplace && (orchFlow.getFlowName().contains("Delete")))) {
581                     if (!isReplace) {
582                         dataObj.getResourceKey().setVfModuleCustomizationId(vfModuleCustomizationUUID);
583                         dataObj.getResourceKey().setVnfCustomizationId(vnfCustomizationUUID);
584                     } else {
585                         if (orchFlow.getFlowName().contains("Delete")) {
586                             dataObj.getResourceKey().setVfModuleCustomizationId(vfModuleCustomizationUUID);
587                             dataObj.getResourceKey().setVnfCustomizationId(vnfCustomizationUUID);
588                         } else {
589                             dataObj.getResourceKey().setVfModuleCustomizationId(replaceVfModuleCustomizationUUID);
590                             dataObj.getResourceKey().setVnfCustomizationId(replaceVnfModuleCustomizationUUID);
591                         }
592                     }
593                     dataObj.getResourceKey().setCvnfModuleCustomizationId(vnfc.getModelCustomizationId());
594                     String vnfcName = vnfc.getVnfcName();
595                     if (vnfcName == null || vnfcName.isEmpty()) {
596                         buildAndThrowException(dataObj.getExecution(), "Exception in create execution list "
597                                 + ": VnfcName does not exist or is null while there is a configuration for the vfModule",
598                                 new Exception("Vnfc and Configuration do not match"));
599                     }
600                     ExecuteBuildingBlock ebb = buildExecuteBuildingBlock(orchFlow, dataObj.getRequestId(),
601                             dataObj.getResourceKey(), dataObj.getApiVersion(), dataObj.getResourceId(),
602                             dataObj.getRequestAction(), dataObj.isaLaCarte(), dataObj.getVnfType(), workflowIdsCopy,
603                             dataObj.getRequestDetails(), false, null, vnfcName, true, null);
604                     flowsToExecuteConfigs.add(ebb);
605                 }
606             }
607         }
608         return flowsToExecuteConfigs;
609     }
610
611     protected void buildAndThrowException(DelegateExecution execution, String msg) {
612         logger.error(msg);
613         execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, msg);
614         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg);
615     }
616
617     protected void buildAndThrowException(DelegateExecution execution, String msg, Exception ex) {
618         logger.error(msg, ex);
619         execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, msg + ex.getMessage());
620         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg + ex.getMessage());
621     }
622
623     protected List<OrchestrationFlow> getVfModuleReplaceBuildingBlocks(ConfigBuildingBlocksDataObject dataObj)
624             throws Exception {
625
626         String vnfId = dataObj.getWorkflowResourceIds().getVnfId();
627         String vfModuleId = dataObj.getWorkflowResourceIds().getVfModuleId();
628
629         logger.debug("BUILDING REPLACE LIST");
630
631         boolean volumeGroupExisted = false;
632         boolean volumeGroupWillExist = false;
633         boolean keepVolumeGroup = false;
634
635         boolean rebuildVolumeGroups = false;
636         if (dataObj.getRequestDetails().getRequestParameters() != null
637                 && dataObj.getRequestDetails().getRequestParameters().getRebuildVolumeGroups() != null) {
638             rebuildVolumeGroups = dataObj.getRequestDetails().getRequestParameters().getRebuildVolumeGroups();
639         }
640         String volumeGroupName = "";
641         Optional<VolumeGroup> volumeGroupFromVfModule =
642                 bbInputSetupUtils.getRelatedVolumeGroupFromVfModule(vnfId, vfModuleId);
643         if (volumeGroupFromVfModule.isPresent()) {
644             String volumeGroupId = volumeGroupFromVfModule.get().getVolumeGroupId();
645             volumeGroupName = volumeGroupFromVfModule.get().getVolumeGroupName();
646             logger.debug("Volume group id of the existing volume group is: " + volumeGroupId);
647             volumeGroupExisted = true;
648             dataObj.getWorkflowResourceIds().setVolumeGroupId(volumeGroupId);
649             dataObj.getReplaceInformation().setOldVolumeGroupName(volumeGroupName);
650         }
651
652         List<OrchestrationFlow> orchFlows = dataObj.getOrchFlows();
653         VfModuleCustomization vfModuleCustomization = catalogDbClient.getVfModuleCustomizationByModelCuztomizationUUID(
654                 dataObj.getRequestDetails().getModelInfo().getModelCustomizationUuid());
655         if (vfModuleCustomization != null && vfModuleCustomization.getVfModule() != null
656                 && vfModuleCustomization.getVfModule().getVolumeHeatTemplate() != null
657                 && vfModuleCustomization.getVolumeHeatEnv() != null) {
658             volumeGroupWillExist = true;
659             if (!volumeGroupExisted) {
660                 String newVolumeGroupId = UUID.randomUUID().toString();
661                 dataObj.getWorkflowResourceIds().setVolumeGroupId(newVolumeGroupId);
662                 dataObj.getReplaceInformation().setOldVolumeGroupName(volumeGroupName);
663                 logger.debug("newVolumeGroupId: " + newVolumeGroupId);
664             }
665         }
666
667         if (volumeGroupExisted && volumeGroupWillExist && !rebuildVolumeGroups) {
668             keepVolumeGroup = true;
669         }
670
671         if (!volumeGroupExisted || keepVolumeGroup) {
672             logger.debug("Filtering out deletion of volume groups");
673             orchFlows = orchFlows.stream().filter(item -> !item.getFlowName().matches(VOLUMEGROUP_DELETE_PATTERN))
674                     .collect(Collectors.toList());
675         }
676         if (!volumeGroupWillExist || keepVolumeGroup) {
677             logger.debug("Filtering out creation of volume groups");
678             orchFlows = orchFlows.stream().filter(item -> !item.getFlowName().matches(VOLUMEGROUP_CREATE_PATTERN))
679                     .collect(Collectors.toList());
680         }
681
682         return orchFlows;
683     }
684
685     protected List<Resource> sortVfModulesByBaseFirst(List<Resource> vfModuleResources) {
686         int count = 0;
687         for (Resource resource : vfModuleResources) {
688             if (resource.isBaseVfModule()) {
689                 Collections.swap(vfModuleResources, 0, count);
690                 break;
691             }
692             count++;
693         }
694         return vfModuleResources;
695     }
696
697     protected List<Resource> sortVfModulesByBaseLast(List<Resource> vfModuleResources) {
698         int count = 0;
699         for (Resource resource : vfModuleResources) {
700             if (resource.isBaseVfModule()) {
701                 Collections.swap(vfModuleResources, vfModuleResources.size() - 1, count);
702                 break;
703             }
704             count++;
705         }
706         return vfModuleResources;
707     }
708
709     private void updateResourceIdsFromAAITraversal(List<ExecuteBuildingBlock> flowsToExecute,
710             List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds, String serviceInstanceId) {
711         for (Pair<WorkflowType, String> pair : aaiResourceIds) {
712             logger.debug(pair.getValue0() + ", " + pair.getValue1());
713         }
714
715         Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE))
716                 .forEach(type -> resourceList.stream().filter(resource -> type.equals(resource.getResourceType()))
717                         .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource.getResourceId(),
718                                 retrieveAAIResourceId(aaiResourceIds, type), null, serviceInstanceId)));
719     }
720
721     private String retrieveAAIResourceId(List<Pair<WorkflowType, String>> aaiResourceIds, WorkflowType resource) {
722         String id = null;
723         for (int i = 0; i < aaiResourceIds.size(); i++) {
724             if (aaiResourceIds.get(i).getValue0() == resource) {
725                 id = aaiResourceIds.get(i).getValue1();
726                 aaiResourceIds.remove(i);
727                 break;
728             }
729         }
730         return id;
731     }
732
733     private void generateResourceIds(List<ExecuteBuildingBlock> flowsToExecute, List<Resource> resourceList,
734             String serviceInstanceId) {
735         Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE))
736                 .forEach(type -> resourceList.stream().filter(resource -> type.equals(resource.getResourceType()))
737                         .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource.getResourceId(),
738                                 null, resource.getVirtualLinkKey(), serviceInstanceId)));
739     }
740
741     protected void updateWorkflowResourceIds(List<ExecuteBuildingBlock> flowsToExecute, WorkflowType resourceType,
742             String key, String id, String virtualLinkKey, String serviceInstanceId) {
743         String resourceId = id;
744         if (resourceId == null) {
745             resourceId = UUID.randomUUID().toString();
746         }
747         for (ExecuteBuildingBlock ebb : flowsToExecute) {
748             if (key != null && key.equalsIgnoreCase(ebb.getBuildingBlock().getKey()) && (ebb.getBuildingBlock()
749                     .getBpmnFlowName().contains(resourceType.toString())
750                     || (ebb.getBuildingBlock().getBpmnFlowName().contains(CONTROLLER)
751                             && ebb.getBuildingBlock().getBpmnScope().equalsIgnoreCase(resourceType.toString())))) {
752                 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
753                 workflowResourceIds.setServiceInstanceId(serviceInstanceId);
754                 WorkflowResourceIdsUtils.setResourceIdByWorkflowType(workflowResourceIds, resourceType, resourceId);
755                 ebb.setWorkflowResourceIds(workflowResourceIds);
756             }
757             if (virtualLinkKey != null && ebb.getBuildingBlock().isVirtualLink()
758                     && virtualLinkKey.equalsIgnoreCase(ebb.getBuildingBlock().getVirtualLinkKey())) {
759                 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
760                 workflowResourceIds.setServiceInstanceId(serviceInstanceId);
761                 workflowResourceIds.setNetworkId(resourceId);
762                 ebb.setWorkflowResourceIds(workflowResourceIds);
763             }
764         }
765     }
766
767     protected CollectionResourceCustomization findCatalogNetworkCollection(DelegateExecution execution,
768             org.onap.so.db.catalog.beans.Service service) {
769         CollectionResourceCustomization networkCollection = null;
770         int count = 0;
771         for (CollectionResourceCustomization collectionCust : service.getCollectionResourceCustomizations()) {
772             if (catalogDbClient.getNetworkCollectionResourceCustomizationByID(
773                     collectionCust.getModelCustomizationUUID()) != null) {
774                 networkCollection = collectionCust;
775                 count++;
776             }
777         }
778         if (count == 0) {
779             return null;
780         } else if (count > 1) {
781             buildAndThrowException(execution,
782                     "Found multiple Network Collections in the Service model, only one per Service is supported.");
783         }
784         return networkCollection;
785     }
786
787     protected void traverseCatalogDbService(DelegateExecution execution, ServiceInstancesRequest sIRequest,
788             List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds)
789             throws JsonProcessingException, VrfBondingServiceException {
790         String modelUUID = sIRequest.getRequestDetails().getModelInfo().getModelVersionId();
791         org.onap.so.db.catalog.beans.Service service = catalogDbClient.getServiceByID(modelUUID);
792
793         if (service == null) {
794             buildAndThrowException(execution, "Could not find the service model in catalog db.");
795         } else {
796             resourceList.add(new Resource(WorkflowType.SERVICE, service.getModelUUID(), false));
797             RelatedInstance relatedVpnBinding =
798                     bbInputSetupUtils.getRelatedInstanceByType(sIRequest.getRequestDetails(), ModelType.vpnBinding);
799             RelatedInstance relatedLocalNetwork =
800                     bbInputSetupUtils.getRelatedInstanceByType(sIRequest.getRequestDetails(), ModelType.network);
801
802             if (relatedVpnBinding != null && relatedLocalNetwork != null) {
803                 traverseVrfConfiguration(aaiResourceIds, resourceList, service, relatedVpnBinding, relatedLocalNetwork);
804             } else {
805                 traverseNetworkCollection(execution, resourceList, service);
806             }
807         }
808     }
809
810     protected void traverseVrfConfiguration(List<Pair<WorkflowType, String>> aaiResourceIds,
811             List<Resource> resourceList, org.onap.so.db.catalog.beans.Service service,
812             RelatedInstance relatedVpnBinding, RelatedInstance relatedLocalNetwork)
813             throws VrfBondingServiceException, JsonProcessingException {
814         org.onap.aai.domain.yang.L3Network aaiLocalNetwork =
815                 bbInputSetupUtils.getAAIL3Network(relatedLocalNetwork.getInstanceId());
816         vrfValidation.vrfServiceValidation(service);
817         vrfValidation.vrfCatalogDbChecks(service);
818         vrfValidation.aaiVpnBindingValidation(relatedVpnBinding.getInstanceId(),
819                 bbInputSetupUtils.getAAIVpnBinding(relatedVpnBinding.getInstanceId()));
820         vrfValidation.aaiNetworkValidation(relatedLocalNetwork.getInstanceId(), aaiLocalNetwork);
821         vrfValidation.aaiSubnetValidation(aaiLocalNetwork);
822         vrfValidation.aaiAggregateRouteValidation(aaiLocalNetwork);
823         vrfValidation.aaiRouteTargetValidation(aaiLocalNetwork);
824         String existingAAIVrfConfiguration = getExistingAAIVrfConfiguration(relatedVpnBinding, aaiLocalNetwork);
825         if (existingAAIVrfConfiguration != null) {
826             aaiResourceIds.add(new Pair<>(WorkflowType.CONFIGURATION, existingAAIVrfConfiguration));
827         }
828         resourceList.add(new Resource(WorkflowType.CONFIGURATION,
829                 service.getConfigurationCustomizations().get(0).getModelCustomizationUUID(), false));
830
831     }
832
833     protected String getExistingAAIVrfConfiguration(RelatedInstance relatedVpnBinding,
834             org.onap.aai.domain.yang.L3Network aaiLocalNetwork)
835             throws JsonProcessingException, VrfBondingServiceException {
836         Optional<Relationships> relationshipsOp = new AAIResultWrapper(
837                 new AAICommonObjectMapperProvider().getMapper().writeValueAsString(aaiLocalNetwork)).getRelationships();
838         if (relationshipsOp.isPresent()) {
839             List<AAIResultWrapper> configurationsRelatedToLocalNetwork =
840                     relationshipsOp.get().getByType(Types.CONFIGURATION);
841             if (configurationsRelatedToLocalNetwork.size() > 1) {
842                 throw new VrfBondingServiceException(
843                         "Network: " + aaiLocalNetwork.getNetworkId() + " has more than 1 configuration related to it");
844             }
845             if (configurationsRelatedToLocalNetwork.size() == 1) {
846                 AAIResultWrapper configWrapper = configurationsRelatedToLocalNetwork.get(0);
847                 Optional<Configuration> relatedConfiguration = configWrapper.asBean(Configuration.class);
848                 if (relatedConfiguration.isPresent() && vrfConfigurationAlreadyExists(relatedVpnBinding,
849                         relatedConfiguration.get(), configWrapper)) {
850                     return relatedConfiguration.get().getConfigurationId();
851                 }
852             }
853         }
854         return null;
855     }
856
857     protected boolean vrfConfigurationAlreadyExists(RelatedInstance relatedVpnBinding, Configuration vrfConfiguration,
858             AAIResultWrapper configWrapper) throws VrfBondingServiceException {
859         if ("VRF-ENTRY".equalsIgnoreCase(vrfConfiguration.getConfigurationType())) {
860             Optional<Relationships> relationshipsConfigOp = configWrapper.getRelationships();
861             if (relationshipsConfigOp.isPresent()) {
862                 Optional<VpnBinding> relatedInfraVpnBindingOp =
863                         workflowActionUtils.extractRelationshipsVpnBinding(relationshipsConfigOp.get());
864                 if (relatedInfraVpnBindingOp.isPresent()) {
865                     VpnBinding relatedInfraVpnBinding = relatedInfraVpnBindingOp.get();
866                     if (!relatedInfraVpnBinding.getVpnId().equalsIgnoreCase(relatedVpnBinding.getInstanceId())) {
867                         throw new VrfBondingServiceException("Configuration: " + vrfConfiguration.getConfigurationId()
868                                 + " is not connected to the same vpn binding id provided in request: "
869                                 + relatedVpnBinding.getInstanceId());
870                     } else {
871                         return true;
872                     }
873                 }
874             }
875         }
876         return false;
877     }
878
879     protected void traverseNetworkCollection(DelegateExecution execution, List<Resource> resourceList,
880             org.onap.so.db.catalog.beans.Service service) {
881         if (isVnfCustomizationsInTheService(service)) {
882             buildAndThrowException(execution,
883                     "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");
884         }
885         if (isPnfCustomizationsInTheService(service)) {
886             buildAndThrowException(execution,
887                     "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");
888         }
889         List<CollectionResourceCustomization> customizations = service.getCollectionResourceCustomizations();
890         if (customizations.isEmpty()) {
891             logger.debug("No Collections found. CollectionResourceCustomization list is empty.");
892         } else {
893             CollectionResourceCustomization collectionResourceCustomization =
894                     findCatalogNetworkCollection(execution, service);
895             traverseNetworkCollectionResourceCustomization(resourceList, collectionResourceCustomization);
896         }
897         traverseNetworkCollectionCustomization(resourceList, service);
898     }
899
900     private void traverseNetworkCollectionResourceCustomization(List<Resource> resourceList,
901             CollectionResourceCustomization collectionResourceCustomization) {
902         if (collectionResourceCustomizationShouldNotBeProcessed(resourceList, collectionResourceCustomization))
903             return;
904         int minNetworks = 0;
905         org.onap.so.db.catalog.beans.InstanceGroup instanceGroup =
906                 collectionResourceCustomization.getCollectionResource().getInstanceGroup();
907         CollectionResourceInstanceGroupCustomization collectionInstCust = null;
908         if (!instanceGroup.getCollectionInstanceGroupCustomizations().isEmpty()) {
909             for (CollectionResourceInstanceGroupCustomization collectionInstanceGroupTemp : instanceGroup
910                     .getCollectionInstanceGroupCustomizations()) {
911                 if (collectionInstanceGroupTemp.getModelCustomizationUUID()
912                         .equalsIgnoreCase(collectionResourceCustomization.getModelCustomizationUUID())) {
913                     collectionInstCust = collectionInstanceGroupTemp;
914                     break;
915                 }
916             }
917             if (interfaceNetworkQuantityIsAvailableInCollection(collectionInstCust)) {
918                 minNetworks = collectionInstCust.getSubInterfaceNetworkQuantity();
919             }
920         }
921         logger.debug("minNetworks: {}", minNetworks);
922         CollectionNetworkResourceCustomization collectionNetworkResourceCust =
923                 getCollectionNetworkResourceCustomization(collectionResourceCustomization, instanceGroup);
924         for (int i = 0; i < minNetworks; i++) {
925             if (collectionNetworkResourceCust != null) {
926                 Resource resource = new Resource(WorkflowType.VIRTUAL_LINK,
927                         collectionNetworkResourceCust.getModelCustomizationUUID(), false);
928                 resource.setVirtualLinkKey(Integer.toString(i));
929                 resourceList.add(resource);
930             }
931         }
932     }
933
934     private CollectionNetworkResourceCustomization getCollectionNetworkResourceCustomization(
935             CollectionResourceCustomization collectionResourceCustomization, InstanceGroup instanceGroup) {
936         CollectionNetworkResourceCustomization collectionNetworkResourceCust = null;
937         for (CollectionNetworkResourceCustomization collectionNetworkTemp : instanceGroup
938                 .getCollectionNetworkResourceCustomizations()) {
939             if (collectionNetworkTemp.getNetworkResourceCustomization().getModelCustomizationUUID()
940                     .equalsIgnoreCase(collectionResourceCustomization.getModelCustomizationUUID())) {
941                 collectionNetworkResourceCust = collectionNetworkTemp;
942                 break;
943             }
944         }
945         return collectionNetworkResourceCust;
946     }
947
948     private boolean collectionResourceCustomizationShouldNotBeProcessed(List<Resource> resourceList,
949             CollectionResourceCustomization collectionResourceCustomization) {
950         if (collectionResourceCustomization == null) {
951             logger.debug("No Network Collection Customization found");
952             return true;
953         }
954         resourceList.add(new Resource(WorkflowType.NETWORKCOLLECTION,
955                 collectionResourceCustomization.getModelCustomizationUUID(), false));
956         logger.debug("Found a network collection");
957         if (collectionResourceCustomization.getCollectionResource() == null) {
958             logger.debug("No Network Collection found. collectionResource is null");
959             return true;
960         }
961         if (collectionResourceCustomization.getCollectionResource().getInstanceGroup() == null) {
962             logger.debug("No Instance Group found for network collection.");
963             return true;
964         }
965         String toscaNodeType =
966                 collectionResourceCustomization.getCollectionResource().getInstanceGroup().getToscaNodeType();
967         if (!toscaNodeTypeHasNetworkCollection(toscaNodeType)) {
968             logger.debug("Instance Group tosca node type does not contain NetworkCollection:  {}", toscaNodeType);
969             return true;
970         }
971         return false;
972     }
973
974     private boolean interfaceNetworkQuantityIsAvailableInCollection(
975             CollectionResourceInstanceGroupCustomization collectionInstCust) {
976         return collectionInstCust != null && collectionInstCust.getSubInterfaceNetworkQuantity() != null;
977     }
978
979     private boolean toscaNodeTypeHasNetworkCollection(String toscaNodeType) {
980         return toscaNodeType != null && toscaNodeType.contains(NETWORKCOLLECTION);
981     }
982
983     private void traverseNetworkCollectionCustomization(List<Resource> resourceList,
984             org.onap.so.db.catalog.beans.Service service) {
985         if (isNetworkCollectionInTheResourceList(resourceList)) {
986             return;
987         }
988         if (service.getNetworkCustomizations() == null) {
989             logger.debug("No networks were found on this service model");
990             return;
991         }
992         for (int i = 0; i < service.getNetworkCustomizations().size(); i++) {
993             resourceList.add(new Resource(WorkflowType.NETWORK,
994                     service.getNetworkCustomizations().get(i).getModelCustomizationUUID(), false));
995         }
996     }
997
998     private boolean isNetworkCollectionInTheResourceList(List<Resource> resourceList) {
999         return resourceList.stream().anyMatch(x -> WorkflowType.NETWORKCOLLECTION == x.getResourceType());
1000     }
1001
1002     private boolean isVnfCustomizationsInTheService(org.onap.so.db.catalog.beans.Service service) {
1003         return !(service.getVnfCustomizations() == null || service.getVnfCustomizations().isEmpty());
1004     }
1005
1006     private boolean isPnfCustomizationsInTheService(org.onap.so.db.catalog.beans.Service service) {
1007         return !(service.getPnfCustomizations() == null || service.getPnfCustomizations().isEmpty());
1008     }
1009
1010     protected void traverseAAIService(DelegateExecution execution, List<Resource> resourceList, String resourceId,
1011             List<Pair<WorkflowType, String>> aaiResourceIds) {
1012         try {
1013             ServiceInstance serviceInstanceAAI = bbInputSetupUtils.getAAIServiceInstanceById(resourceId);
1014             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO =
1015                     bbInputSetup.getExistingServiceInstance(serviceInstanceAAI);
1016             resourceList.add(new Resource(WorkflowType.SERVICE, serviceInstanceMSO.getServiceInstanceId(), false));
1017             traverseServiceInstanceMSOVnfs(resourceList, aaiResourceIds, serviceInstanceMSO);
1018             traverseServiceInstanceMSOPnfs(resourceList, aaiResourceIds, serviceInstanceMSO);
1019             if (serviceInstanceMSO.getNetworks() != null) {
1020                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.L3Network network : serviceInstanceMSO
1021                         .getNetworks()) {
1022                     aaiResourceIds.add(new Pair<>(WorkflowType.NETWORK, network.getNetworkId()));
1023                     resourceList.add(new Resource(WorkflowType.NETWORK, network.getNetworkId(), false));
1024                 }
1025             }
1026             if (serviceInstanceMSO.getCollection() != null) {
1027                 logger.debug("found networkcollection");
1028                 aaiResourceIds
1029                         .add(new Pair<>(WorkflowType.NETWORKCOLLECTION, serviceInstanceMSO.getCollection().getId()));
1030                 resourceList.add(new Resource(WorkflowType.NETWORKCOLLECTION,
1031                         serviceInstanceMSO.getCollection().getId(), false));
1032             }
1033             if (serviceInstanceMSO.getConfigurations() != null) {
1034                 for (Configuration config : serviceInstanceMSO.getConfigurations()) {
1035                     Optional<org.onap.aai.domain.yang.Configuration> aaiConfig =
1036                             aaiConfigurationResources.getConfiguration(config.getConfigurationId());
1037                     if (aaiConfig.isPresent() && aaiConfig.get().getRelationshipList() != null) {
1038                         for (Relationship relationship : aaiConfig.get().getRelationshipList().getRelationship()) {
1039                             if (relationship.getRelatedTo().contains("vnfc")
1040                                     || relationship.getRelatedTo().contains("vpn-binding")) {
1041                                 aaiResourceIds.add(new Pair<>(WorkflowType.CONFIGURATION, config.getConfigurationId()));
1042                                 resourceList.add(
1043                                         new Resource(WorkflowType.CONFIGURATION, config.getConfigurationId(), false));
1044                                 break;
1045                             }
1046                         }
1047                     }
1048                 }
1049             }
1050         } catch (Exception ex) {
1051             logger.error("Exception in traverseAAIService", ex);
1052             buildAndThrowException(execution,
1053                     "Could not find existing Service Instance or related Instances to execute the request on.");
1054         }
1055     }
1056
1057     private void traverseServiceInstanceMSOVnfs(List<Resource> resourceList,
1058             List<Pair<WorkflowType, String>> aaiResourceIds,
1059             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO) {
1060         if (serviceInstanceMSO.getVnfs() == null) {
1061             return;
1062         }
1063         for (org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf : serviceInstanceMSO.getVnfs()) {
1064             aaiResourceIds.add(new Pair<>(WorkflowType.VNF, vnf.getVnfId()));
1065             resourceList.add(new Resource(WorkflowType.VNF, vnf.getVnfId(), false));
1066             traverseVnfModules(resourceList, aaiResourceIds, vnf);
1067             if (vnf.getVolumeGroups() != null) {
1068                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup volumeGroup : vnf.getVolumeGroups()) {
1069                     aaiResourceIds.add(new Pair<>(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId()));
1070                     resourceList.add(new Resource(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId(), false));
1071                 }
1072             }
1073         }
1074     }
1075
1076     private void traverseServiceInstanceMSOPnfs(List<Resource> resourceList,
1077             List<Pair<WorkflowType, String>> aaiResourceIds,
1078             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO) {
1079         if (serviceInstanceMSO.getPnfs() == null) {
1080             return;
1081         }
1082         for (org.onap.so.bpmn.servicedecomposition.bbobjects.Pnf pnf : serviceInstanceMSO.getPnfs()) {
1083             aaiResourceIds.add(new Pair<>(WorkflowType.PNF, pnf.getPnfId()));
1084             resourceList.add(new Resource(WorkflowType.PNF, pnf.getPnfId(), false));
1085         }
1086     }
1087
1088     private void traverseVnfModules(List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds,
1089             org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf) {
1090         if (vnf.getVfModules() == null) {
1091             return;
1092         }
1093         for (VfModule vfModule : vnf.getVfModules()) {
1094             aaiResourceIds.add(new Pair<>(WorkflowType.VFMODULE, vfModule.getVfModuleId()));
1095             Resource resource = new Resource(WorkflowType.VFMODULE, vfModule.getVfModuleId(), false);
1096             resource.setBaseVfModule(vfModule.getModelInfoVfModule().getIsBaseBoolean());
1097             resourceList.add(resource);
1098         }
1099     }
1100
1101     private void traverseAAIVnf(DelegateExecution execution, List<Resource> resourceList, String serviceId,
1102             String vnfId, List<Pair<WorkflowType, String>> aaiResourceIds) {
1103         try {
1104             ServiceInstance serviceInstanceAAI = bbInputSetupUtils.getAAIServiceInstanceById(serviceId);
1105             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO =
1106                     bbInputSetup.getExistingServiceInstance(serviceInstanceAAI);
1107             resourceList.add(new Resource(WorkflowType.SERVICE, serviceInstanceMSO.getServiceInstanceId(), false));
1108             if (serviceInstanceMSO.getVnfs() != null) {
1109                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf : serviceInstanceMSO.getVnfs()) {
1110                     if (vnf.getVnfId().equals(vnfId)) {
1111                         aaiResourceIds.add(new Pair<>(WorkflowType.VNF, vnf.getVnfId()));
1112                         resourceList.add(new Resource(WorkflowType.VNF, vnf.getVnfId(), false));
1113                         if (vnf.getVfModules() != null) {
1114                             for (VfModule vfModule : vnf.getVfModules()) {
1115                                 aaiResourceIds.add(new Pair<>(WorkflowType.VFMODULE, vfModule.getVfModuleId()));
1116                                 resourceList.add(new Resource(WorkflowType.VFMODULE, vfModule.getVfModuleId(), false));
1117                                 findConfigurationsInsideVfModule(execution, vnf.getVnfId(), vfModule.getVfModuleId(),
1118                                         resourceList, aaiResourceIds);
1119                             }
1120                         }
1121                         if (vnf.getVolumeGroups() != null) {
1122                             for (org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup volumeGroup : vnf
1123                                     .getVolumeGroups()) {
1124                                 aaiResourceIds
1125                                         .add(new Pair<>(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId()));
1126                                 resourceList.add(
1127                                         new Resource(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId(), false));
1128                             }
1129                         }
1130                         break;
1131                     }
1132                 }
1133             }
1134         } catch (Exception ex) {
1135             logger.error("Exception in traverseAAIVnf", ex);
1136             buildAndThrowException(execution,
1137                     "Could not find existing Vnf or related Instances to execute the request on.");
1138         }
1139     }
1140
1141     private void customTraverseAAIVnf(DelegateExecution execution, List<Resource> resourceList, String serviceId,
1142             String vnfId, List<Pair<WorkflowType, String>> aaiResourceIds) {
1143         try {
1144             ServiceInstance serviceInstanceAAI = bbInputSetupUtils.getAAIServiceInstanceById(serviceId);
1145             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO =
1146                     bbInputSetup.getExistingServiceInstance(serviceInstanceAAI);
1147             resourceList.add(new Resource(WorkflowType.SERVICE, serviceInstanceMSO.getServiceInstanceId(), false));
1148             if (serviceInstanceMSO.getVnfs() != null) {
1149                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf : serviceInstanceMSO.getVnfs()) {
1150                     if (vnf.getVnfId().equals(vnfId)) {
1151                         aaiResourceIds.add(new Pair<>(WorkflowType.VNF, vnf.getVnfId()));
1152
1153                         String vnfCustomizationUUID =
1154                                 bbInputSetupUtils.getAAIGenericVnf(vnfId).getModelCustomizationId();
1155                         resourceList.add(new Resource(WorkflowType.VNF, vnfCustomizationUUID, false));
1156
1157                         if (vnf.getVfModules() != null) {
1158                             for (VfModule vfModule : vnf.getVfModules()) {
1159                                 aaiResourceIds.add(new Pair<>(WorkflowType.VFMODULE, vfModule.getVfModuleId()));
1160                                 resourceList.add(new Resource(WorkflowType.VFMODULE, vfModule.getVfModuleId(), false));
1161                                 findConfigurationsInsideVfModule(execution, vnf.getVnfId(), vfModule.getVfModuleId(),
1162                                         resourceList, aaiResourceIds);
1163                             }
1164                         }
1165                         if (vnf.getVolumeGroups() != null) {
1166                             for (org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup volumeGroup : vnf
1167                                     .getVolumeGroups()) {
1168                                 aaiResourceIds
1169                                         .add(new Pair<>(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId()));
1170                                 resourceList.add(
1171                                         new Resource(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId(), false));
1172                             }
1173                         }
1174                         break;
1175                     }
1176                 }
1177             }
1178         } catch (Exception ex) {
1179             logger.error("Exception in customTraverseAAIVnf", ex);
1180             buildAndThrowException(execution,
1181                     "Could not find existing Vnf or related Instances to execute the request on.");
1182         }
1183
1184     }
1185
1186     private void findConfigurationsInsideVfModule(DelegateExecution execution, String vnfId, String vfModuleId,
1187             List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds) {
1188         try {
1189             org.onap.aai.domain.yang.VfModule aaiVfModule = bbInputSetupUtils.getAAIVfModule(vnfId, vfModuleId);
1190             AAIResultWrapper vfModuleWrapper = new AAIResultWrapper(
1191                     new AAICommonObjectMapperProvider().getMapper().writeValueAsString(aaiVfModule));
1192             Optional<Relationships> relationshipsOp;
1193             relationshipsOp = vfModuleWrapper.getRelationships();
1194             if (relationshipsOp.isPresent()) {
1195                 relationshipsOp = workflowActionUtils.extractRelationshipsVnfc(relationshipsOp.get());
1196                 if (relationshipsOp.isPresent()) {
1197                     Optional<Configuration> config =
1198                             workflowActionUtils.extractRelationshipsConfiguration(relationshipsOp.get());
1199                     if (config.isPresent()) {
1200                         aaiResourceIds.add(new Pair<>(WorkflowType.CONFIGURATION, config.get().getConfigurationId()));
1201                         resourceList.add(
1202                                 new Resource(WorkflowType.CONFIGURATION, config.get().getConfigurationId(), false));
1203                     }
1204                 }
1205             }
1206         } catch (Exception ex) {
1207             logger.error("Exception in findConfigurationsInsideVfModule", ex);
1208             buildAndThrowException(execution, "Failed to find Configuration object from the vfModule.");
1209         }
1210     }
1211
1212     protected WorkflowResourceIds populateResourceIdsFromApiHandler(DelegateExecution execution) {
1213         return WorkflowResourceIdsUtils.getWorkflowResourceIdsFromExecution(execution);
1214     }
1215
1216     protected Resource extractResourceIdAndTypeFromUri(String uri) {
1217         Pattern patt = Pattern.compile("[vV]\\d+.*?(?:(?:/(?<type>" + SUPPORTEDTYPES
1218                 + ")(?:/(?<id>[^/]+))?)(?:/(?<action>[^/]+))?(?:/resume)?)?$");
1219         Matcher m = patt.matcher(uri);
1220         boolean generated = false;
1221
1222         if (m.find()) {
1223             logger.debug("found match on {} : {} ", uri, m);
1224             String type = m.group("type");
1225             String id = m.group("id");
1226             String action = m.group("action");
1227             if (type == null) {
1228                 throw new IllegalArgumentException("Uri could not be parsed. No type found. " + uri);
1229             }
1230             if (action == null) {
1231                 if (type.equals(SERVICE_INSTANCES) && (id == null || "assign".equals(id))) {
1232                     id = UUID.randomUUID().toString();
1233                     generated = true;
1234                 } else if (type.equals(VF_MODULES) && "scaleOut".equals(id)) {
1235                     id = UUID.randomUUID().toString();
1236                     generated = true;
1237                 }
1238             } else {
1239                 if (action.matches(SUPPORTEDTYPES)) {
1240                     id = UUID.randomUUID().toString();
1241                     generated = true;
1242                     type = action;
1243                 }
1244             }
1245             return new Resource(WorkflowType.fromString(convertTypeFromPlural(type)), id, generated);
1246         } else {
1247             throw new IllegalArgumentException("Uri could not be parsed: " + uri);
1248         }
1249     }
1250
1251     protected String convertTypeFromPlural(String type) {
1252         if (!type.matches(SUPPORTEDTYPES)) {
1253             return type;
1254         } else {
1255             if (type.equals(SERVICE_INSTANCES)) {
1256                 return SERVICE;
1257             } else {
1258                 return type.substring(0, 1).toUpperCase() + type.substring(1, type.length() - 1);
1259             }
1260         }
1261     }
1262
1263     protected List<ExecuteBuildingBlock> sortExecutionPathByObjectForVlanTagging(List<ExecuteBuildingBlock> orchFlows,
1264             String requestAction) {
1265         List<ExecuteBuildingBlock> sortedOrchFlows = new ArrayList<>();
1266         if (requestAction.equals(CREATE_INSTANCE)) {
1267             for (ExecuteBuildingBlock ebb : orchFlows) {
1268                 if (ebb.getBuildingBlock().getBpmnFlowName().equals("AssignNetworkBB")) {
1269                     String key = ebb.getBuildingBlock().getKey();
1270                     boolean isVirtualLink = Boolean.TRUE.equals(ebb.getBuildingBlock().isVirtualLink());
1271                     String virtualLinkKey = ebb.getBuildingBlock().getVirtualLinkKey();
1272                     sortedOrchFlows.add(ebb);
1273                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
1274                         if (!isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
1275                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
1276                             sortedOrchFlows.add(ebb2);
1277                             break;
1278                         }
1279                         if (isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
1280                                 && ebb2.getBuildingBlock().getVirtualLinkKey().equalsIgnoreCase(virtualLinkKey)) {
1281                             sortedOrchFlows.add(ebb2);
1282                             break;
1283                         }
1284                     }
1285                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
1286                         if (!isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)
1287                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
1288                             sortedOrchFlows.add(ebb2);
1289                             break;
1290                         }
1291                         if (isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)
1292                                 && ebb2.getBuildingBlock().getVirtualLinkKey().equalsIgnoreCase(virtualLinkKey)) {
1293                             sortedOrchFlows.add(ebb2);
1294                             break;
1295                         }
1296                     }
1297                 } else if (ebb.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
1298                         || ebb.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)) {
1299                     continue;
1300                 } else if (!"".equals(ebb.getBuildingBlock().getBpmnFlowName())) {
1301                     sortedOrchFlows.add(ebb);
1302                 }
1303             }
1304         } else if (requestAction.equals("deleteInstance")) {
1305             for (ExecuteBuildingBlock ebb : orchFlows) {
1306                 if (ebb.getBuildingBlock().getBpmnFlowName().equals("DeactivateNetworkBB")) {
1307                     sortedOrchFlows.add(ebb);
1308                     String key = ebb.getBuildingBlock().getKey();
1309                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
1310                         if (ebb2.getBuildingBlock().getBpmnFlowName().equals("DeleteNetworkBB")
1311                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
1312                             sortedOrchFlows.add(ebb2);
1313                             break;
1314                         }
1315                     }
1316                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
1317                         if (ebb2.getBuildingBlock().getBpmnFlowName().equals("UnassignNetworkBB")
1318                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
1319                             sortedOrchFlows.add(ebb2);
1320                             break;
1321                         }
1322                     }
1323                 } else if (ebb.getBuildingBlock().getBpmnFlowName().equals("DeleteNetworkBB")
1324                         || ebb.getBuildingBlock().getBpmnFlowName().equals("UnassignNetworkBB")) {
1325                     continue;
1326                 } else if (!ebb.getBuildingBlock().getBpmnFlowName().equals("")) {
1327                     sortedOrchFlows.add(ebb);
1328                 }
1329             }
1330         }
1331         return sortedOrchFlows;
1332     }
1333
1334     private void addBuildingBlockToExecuteBBList(List<ExecuteBuildingBlock> flowsToExecute, List<Resource> resourceList,
1335             WorkflowType workflowType, OrchestrationFlow orchFlow, String requestId, String apiVersion,
1336             String resourceId, String requestAction, String vnfType, WorkflowResourceIds workflowResourceIds,
1337             RequestDetails requestDetails, boolean isVirtualLink, boolean isConfiguration) {
1338
1339         resourceList.stream().filter(resource -> resource.getResourceType().equals(workflowType))
1340                 .forEach(resource -> flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resource,
1341                         apiVersion, resourceId, requestAction, false, vnfType, workflowResourceIds, requestDetails,
1342                         isVirtualLink, resource.getVirtualLinkKey(), null, isConfiguration, null)));
1343     }
1344
1345     protected List<ExecuteBuildingBlock> buildExecuteBuildingBlockList(List<OrchestrationFlow> orchFlows,
1346             List<Resource> resourceList, String requestId, String apiVersion, String resourceId, String requestAction,
1347             String vnfType, WorkflowResourceIds workflowResourceIds, RequestDetails requestDetails,
1348             boolean replaceVnf) {
1349         List<ExecuteBuildingBlock> flowsToExecute = new ArrayList<>();
1350         for (OrchestrationFlow orchFlow : orchFlows) {
1351             if (orchFlow.getFlowName().contains(SERVICE)) {
1352                 if (!replaceVnf) {
1353                     workflowResourceIds.setServiceInstanceId(resourceId);
1354                 }
1355                 addBuildingBlockToExecuteBBList(flowsToExecute, resourceList, WorkflowType.SERVICE, orchFlow, requestId,
1356                         apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails, false,
1357                         false);
1358             } else if (orchFlow.getFlowName().contains(VNF) || (orchFlow.getFlowName().contains(CONTROLLER)
1359                     && (VNF).equalsIgnoreCase(orchFlow.getBpmnScope()))) {
1360                 addBuildingBlockToExecuteBBList(flowsToExecute, resourceList, WorkflowType.VNF, orchFlow, requestId,
1361                         apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails, false,
1362                         false);
1363             } else if (orchFlow.getFlowName().contains(PNF) || (orchFlow.getFlowName().contains(CONTROLLER)
1364                     && (PNF).equalsIgnoreCase(orchFlow.getBpmnScope()))) {
1365                 addBuildingBlockToExecuteBBList(flowsToExecute, resourceList, WorkflowType.PNF, orchFlow, requestId,
1366                         apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails, false,
1367                         false);
1368             } else if (orchFlow.getFlowName().contains(NETWORK)
1369                     && !orchFlow.getFlowName().contains(NETWORKCOLLECTION)) {
1370                 addBuildingBlockToExecuteBBList(flowsToExecute, resourceList, WorkflowType.NETWORK, orchFlow, requestId,
1371                         apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails, false,
1372                         false);
1373                 addBuildingBlockToExecuteBBList(flowsToExecute, resourceList, WorkflowType.VIRTUAL_LINK, orchFlow,
1374                         requestId, apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails,
1375                         true, false);
1376             } else if (orchFlow.getFlowName().contains(VFMODULE) || (orchFlow.getFlowName().contains(CONTROLLER)
1377                     && (VFMODULE).equalsIgnoreCase(orchFlow.getBpmnScope()))) {
1378                 List<Resource> vfModuleResourcesSorted;
1379                 if (requestAction.equals(CREATE_INSTANCE) || requestAction.equals(ASSIGNINSTANCE)
1380                         || requestAction.equals("activateInstance")) {
1381                     vfModuleResourcesSorted = sortVfModulesByBaseFirst(resourceList.stream()
1382                             .filter(x -> WorkflowType.VFMODULE == x.getResourceType()).collect(Collectors.toList()));
1383                 } else {
1384                     vfModuleResourcesSorted = sortVfModulesByBaseLast(resourceList.stream()
1385                             .filter(x -> WorkflowType.VFMODULE == x.getResourceType()).collect(Collectors.toList()));
1386                 }
1387                 for (Resource resource : vfModuleResourcesSorted) {
1388                     flowsToExecute.add(buildExecuteBuildingBlock(orchFlow, requestId, resource, apiVersion, resourceId,
1389                             requestAction, false, vnfType, workflowResourceIds, requestDetails, false, null, null,
1390                             false, null));
1391                 }
1392             } else if (orchFlow.getFlowName().contains(VOLUMEGROUP)) {
1393                 if (requestAction.equalsIgnoreCase(REPLACEINSTANCE)
1394                         || requestAction.equalsIgnoreCase(REPLACEINSTANCERETAINASSIGNMENTS)) {
1395                     logger.debug("Replacing workflow resource id by volume group id");
1396                     resourceId = workflowResourceIds.getVolumeGroupId();
1397                 }
1398                 addBuildingBlockToExecuteBBList(flowsToExecute, resourceList, WorkflowType.VOLUMEGROUP, orchFlow,
1399                         requestId, apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails,
1400                         false, false);
1401             } else if (orchFlow.getFlowName().contains(NETWORKCOLLECTION)) {
1402                 addBuildingBlockToExecuteBBList(flowsToExecute, resourceList, WorkflowType.NETWORKCOLLECTION, orchFlow,
1403                         requestId, apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails,
1404                         false, false);
1405             } else if (orchFlow.getFlowName().contains(CONFIGURATION)) {
1406                 addBuildingBlockToExecuteBBList(flowsToExecute, resourceList, WorkflowType.CONFIGURATION, orchFlow,
1407                         requestId, apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails,
1408                         false, true);
1409             } else {
1410                 flowsToExecute
1411                         .add(buildExecuteBuildingBlock(orchFlow, requestId, null, apiVersion, resourceId, requestAction,
1412                                 false, vnfType, workflowResourceIds, requestDetails, false, null, null, false, null));
1413             }
1414         }
1415         return flowsToExecute;
1416     }
1417
1418     protected ExecuteBuildingBlock buildExecuteBuildingBlock(OrchestrationFlow orchFlow, String requestId,
1419             Resource resource, String apiVersion, String resourceId, String requestAction, boolean aLaCarte,
1420             String vnfType, WorkflowResourceIds workflowResourceIds, RequestDetails requestDetails,
1421             boolean isVirtualLink, String virtualLinkKey, String vnfcName, boolean isConfiguration,
1422             ReplaceInstanceRelatedInformation replaceInfo) {
1423
1424         BuildingBlock buildingBlock =
1425                 new BuildingBlock().setBpmnFlowName(orchFlow.getFlowName()).setMsoId(UUID.randomUUID().toString())
1426                         .setIsVirtualLink(isVirtualLink).setVirtualLinkKey(virtualLinkKey)
1427                         .setKey(Optional.ofNullable(resource).map(Resource::getResourceId).orElse(""));
1428         Optional.ofNullable(orchFlow.getBpmnAction()).ifPresent(buildingBlock::setBpmnAction);
1429         Optional.ofNullable(orchFlow.getBpmnScope()).ifPresent(buildingBlock::setBpmnScope);
1430         String oldVolumeGroupName = "";
1431         if (replaceInfo != null) {
1432             oldVolumeGroupName = replaceInfo.getOldVolumeGroupName();
1433         }
1434         if (resource != null
1435                 && (orchFlow.getFlowName().contains(VOLUMEGROUP) && (requestAction.equalsIgnoreCase(REPLACEINSTANCE)
1436                         || requestAction.equalsIgnoreCase(REPLACEINSTANCERETAINASSIGNMENTS)))) {
1437             logger.debug("Setting resourceId to volume group id for volume group flow on replace");
1438             resourceId = workflowResourceIds.getVolumeGroupId();
1439         }
1440
1441         ExecuteBuildingBlock executeBuildingBlock = new ExecuteBuildingBlock().setApiVersion(apiVersion)
1442                 .setaLaCarte(aLaCarte).setRequestAction(requestAction).setResourceId(resourceId).setVnfType(vnfType)
1443                 .setWorkflowResourceIds(workflowResourceIds).setRequestId(requestId).setBuildingBlock(buildingBlock)
1444                 .setRequestDetails(requestDetails).setOldVolumeGroupName(oldVolumeGroupName);
1445
1446         if (resource != null && (isConfiguration || resource.getResourceType().equals(WorkflowType.CONFIGURATION))) {
1447             ConfigurationResourceKeys configurationResourceKeys = getConfigurationResourceKeys(resource, vnfcName);
1448             executeBuildingBlock.setConfigurationResourceKeys(configurationResourceKeys);
1449         }
1450         return executeBuildingBlock;
1451     }
1452
1453     private ConfigurationResourceKeys getConfigurationResourceKeys(Resource resource, String vnfcName) {
1454         ConfigurationResourceKeys configurationResourceKeys = new ConfigurationResourceKeys();
1455         Optional.ofNullable(vnfcName).ifPresent(configurationResourceKeys::setVnfcName);
1456         configurationResourceKeys.setCvnfcCustomizationUUID(resource.getCvnfModuleCustomizationId());
1457         configurationResourceKeys.setVfModuleCustomizationUUID(resource.getVfModuleCustomizationId());
1458         configurationResourceKeys.setVnfResourceCustomizationUUID(resource.getVnfCustomizationId());
1459         return configurationResourceKeys;
1460     }
1461
1462     protected List<OrchestrationFlow> queryNorthBoundRequestCatalogDb(DelegateExecution execution, String requestAction,
1463             WorkflowType resourceName, boolean aLaCarte, String cloudOwner) {
1464         return this.queryNorthBoundRequestCatalogDb(execution, requestAction, resourceName, aLaCarte, cloudOwner, "");
1465     }
1466
1467     protected List<OrchestrationFlow> queryNorthBoundRequestCatalogDb(DelegateExecution execution, String requestAction,
1468             WorkflowType resourceName, boolean aLaCarte, String cloudOwner, String serviceType) {
1469         List<OrchestrationFlow> listToExecute = new ArrayList<>();
1470         NorthBoundRequest northBoundRequest;
1471         if (serviceType.equalsIgnoreCase(SERVICE_TYPE_TRANSPORT)
1472                 || serviceType.equalsIgnoreCase(SERVICE_TYPE_BONDING)) {
1473             northBoundRequest =
1474                     catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwnerAndServiceType(
1475                             requestAction, resourceName.toString(), aLaCarte, cloudOwner, serviceType);
1476         } else {
1477             northBoundRequest = catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwner(
1478                     requestAction, resourceName.toString(), aLaCarte, cloudOwner);
1479         }
1480         if (northBoundRequest == null) {
1481             northBoundRequest = catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwner(
1482                     requestAction, resourceName.toString(), aLaCarte, CLOUD_OWNER);
1483         }
1484         if (northBoundRequest == null) {
1485             buildAndThrowException(execution, String.format("The request: %s %s %s is not supported by GR_API.",
1486                     (aLaCarte ? "AlaCarte" : "Macro"), resourceName, requestAction));
1487         } else {
1488             if (northBoundRequest.getIsToplevelflow() != null) {
1489                 execution.setVariable(BBConstants.G_ISTOPLEVELFLOW, northBoundRequest.getIsToplevelflow());
1490             }
1491             List<OrchestrationFlow> flows = northBoundRequest.getOrchestrationFlowList();
1492             if (flows == null) {
1493                 flows = new ArrayList<>();
1494             } else {
1495                 flows.sort(Comparator.comparingInt(OrchestrationFlow::getSequenceNumber));
1496             }
1497             for (OrchestrationFlow flow : flows) {
1498                 if (!flow.getFlowName().contains("BB") && !flow.getFlowName().contains("Activity")) {
1499                     List<OrchestrationFlow> macroQueryFlows =
1500                             catalogDbClient.getOrchestrationFlowByAction(flow.getFlowName());
1501                     listToExecute.addAll(macroQueryFlows);
1502                 } else {
1503                     listToExecute.add(flow);
1504                 }
1505             }
1506         }
1507         return listToExecute;
1508     }
1509
1510     public void handleRuntimeException(DelegateExecution execution) {
1511         StringBuilder wfeExpMsg = new StringBuilder("Runtime error ");
1512         String runtimeErrorMessage;
1513         try {
1514             String javaExpMsg = (String) execution.getVariable("BPMN_javaExpMsg");
1515             if (javaExpMsg != null && !javaExpMsg.isEmpty()) {
1516                 wfeExpMsg.append(": ").append(javaExpMsg);
1517             }
1518             runtimeErrorMessage = wfeExpMsg.toString();
1519             logger.error(runtimeErrorMessage);
1520             execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, runtimeErrorMessage);
1521         } catch (Exception e) {
1522             logger.error("Runtime error", e);
1523             // if runtime message was mulformed
1524             runtimeErrorMessage = "Runtime error";
1525         }
1526         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, runtimeErrorMessage);
1527     }
1528
1529     protected boolean isUriResume(String uri) {
1530         return uri.endsWith("/resume");
1531     }
1532
1533     protected boolean isRequestMacroServiceResume(boolean aLaCarte, WorkflowType resourceType, String requestAction,
1534             String serviceInstanceId) {
1535         return (!aLaCarte && resourceType == WorkflowType.SERVICE
1536                 && (requestAction.equalsIgnoreCase(ASSIGNINSTANCE) || requestAction.equalsIgnoreCase(CREATE_INSTANCE))
1537                 && (serviceInstanceId != null && serviceInstanceId.trim().length() > 1)
1538                 && (bbInputSetupUtils.getAAIServiceInstanceById(serviceInstanceId) != null));
1539     }
1540
1541     protected boolean foundRelated(List<Resource> resourceList) {
1542         return (containsWorkflowType(resourceList, WorkflowType.VNF)
1543                 || containsWorkflowType(resourceList, WorkflowType.PNF)
1544                 || containsWorkflowType(resourceList, WorkflowType.NETWORK)
1545                 || containsWorkflowType(resourceList, WorkflowType.NETWORKCOLLECTION));
1546     }
1547
1548     protected boolean containsWorkflowType(List<Resource> resourceList, WorkflowType workflowType) {
1549         return resourceList.stream().anyMatch(resource -> resource.getResourceType().equals(workflowType));
1550     }
1551
1552     private void fillExecutionDefault(DelegateExecution execution) {
1553         execution.setVariable("sentSyncResponse", false);
1554         execution.setVariable(HOMING, false);
1555         execution.setVariable("calledHoming", false);
1556         execution.setVariable(BBConstants.G_ISTOPLEVELFLOW, true);
1557     }
1558
1559     private void fillExecution(DelegateExecution execution, boolean suppressRollback, String resourceId,
1560             WorkflowType resourceType) {
1561         execution.setVariable("suppressRollback", suppressRollback);
1562         execution.setVariable("resourceId", resourceId);
1563         execution.setVariable("resourceType", resourceType);
1564         execution.setVariable("resourceName", resourceType.toString());
1565     }
1566
1567     private Resource getResource(BBInputSetupUtils bbInputSetupUtils, boolean isResume, boolean alaCarte, String uri,
1568             String requestId) {
1569         if (!alaCarte && isResume) {
1570             logger.debug("replacing URI {}", uri);
1571             uri = bbInputSetupUtils.loadOriginalInfraActiveRequestById(requestId).getRequestUrl();
1572             logger.debug("for RESUME with original value {}", uri);
1573         }
1574         return extractResourceIdAndTypeFromUri(uri);
1575     }
1576
1577     private String getResourceId(Resource resource, String requestAction, RequestDetails requestDetails,
1578             WorkflowResourceIds workflowResourceIds) throws Exception {
1579         if (resource.isGenerated() && requestAction.equalsIgnoreCase("createInstance")
1580                 && requestDetails.getRequestInfo().getInstanceName() != null) {
1581             return aaiResourceIdValidator.validateResourceIdInAAI(resource.getResourceId(), resource.getResourceType(),
1582                     requestDetails.getRequestInfo().getInstanceName(), requestDetails, workflowResourceIds);
1583         } else {
1584             return resource.getResourceId();
1585         }
1586     }
1587
1588     private String getServiceInstanceId(DelegateExecution execution, String resourceId, WorkflowType resourceType) {
1589         String serviceInstanceId = (String) execution.getVariable("serviceInstanceId");
1590         if ((serviceInstanceId == null || serviceInstanceId.isEmpty()) && WorkflowType.SERVICE.equals(resourceType)) {
1591             serviceInstanceId = resourceId;
1592         }
1593         return serviceInstanceId;
1594     }
1595
1596 }