ef0fbc850eab1721fa2cfc3e8aa68f5561143df1
[so.git] / bpmn / so-bpmn-tasks / src / main / java / org / onap / so / bpmn / infrastructure / workflow / tasks / WorkflowAction.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Modifications Copyright (c) 2021 Nokia
10  * ================================================================================
11  * Modifications Copyright (c) 2020 Tech Mahindra
12  * ================================================================================
13  * Modifications Copyright (c) 2021 Orange
14  * ================================================================================
15  * Licensed under the Apache License, Version 2.0 (the "License");
16  * you may not use this file except in compliance with the License.
17  * You may obtain a copy of the License at
18  *
19  *      http://www.apache.org/licenses/LICENSE-2.0
20  *
21  * Unless required by applicable law or agreed to in writing, software
22  * distributed under the License is distributed on an "AS IS" BASIS,
23  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24  * See the License for the specific language governing permissions and
25  * limitations under the License.
26  * ============LICENSE_END=========================================================
27  */
28
29 package org.onap.so.bpmn.infrastructure.workflow.tasks;
30
31 import static org.onap.so.bpmn.infrastructure.service.composition.ServiceCompositionConstants.IS_CHILD_PROCESS;
32 import static org.onap.so.bpmn.infrastructure.service.composition.ServiceCompositionConstants.PARENT_CORRELATION_ID;
33 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.ASSIGN_INSTANCE;
34 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.CONTROLLER;
35 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.CREATE_INSTANCE;
36 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.DELETE_INSTANCE;
37 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.FABRIC_CONFIGURATION;
38 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.RECREATE_INSTANCE;
39 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.REPLACEINSTANCE;
40 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.REPLACEINSTANCERETAINASSIGNMENTS;
41 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.SERVICE;
42 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.UPDATE_INSTANCE;
43 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.HEALTH_CHECK;
44 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.WORKFLOW_ACTION_ERROR_MESSAGE;
45 import java.io.IOException;
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.Comparator;
49 import java.util.HashMap;
50 import java.util.LinkedHashSet;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.Optional;
54 import java.util.Set;
55 import java.util.UUID;
56 import java.util.regex.Matcher;
57 import java.util.regex.Pattern;
58 import java.util.stream.Collectors;
59 import org.apache.commons.lang3.SerializationUtils;
60 import org.apache.commons.lang3.StringUtils;
61 import org.camunda.bpm.engine.delegate.DelegateExecution;
62 import org.javatuples.Pair;
63 import org.onap.aai.domain.yang.Vnfc;
64 import org.onap.aai.domain.yang.VolumeGroup;
65 import org.onap.aaiclient.client.aai.AAIObjectName;
66 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper;
67 import org.onap.aaiclient.client.aai.entities.Relationships;
68 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
69 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
70 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder;
71 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types;
72 import org.onap.so.bpmn.common.BBConstants;
73 import org.onap.so.bpmn.infrastructure.workflow.tasks.ebb.loader.ServiceEBBLoader;
74 import org.onap.so.bpmn.infrastructure.workflow.tasks.ebb.loader.VnfEBBLoader;
75 import org.onap.so.bpmn.infrastructure.workflow.tasks.excpetion.VnfcMultipleRelationshipException;
76 import org.onap.so.bpmn.infrastructure.workflow.tasks.utils.WorkflowResourceIdsUtils;
77 import org.onap.so.bpmn.servicedecomposition.entities.ExecuteBuildingBlock;
78 import org.onap.so.bpmn.servicedecomposition.entities.WorkflowResourceIds;
79 import org.onap.so.bpmn.servicedecomposition.tasks.BBInputSetup;
80 import org.onap.so.bpmn.servicedecomposition.tasks.BBInputSetupUtils;
81 import org.onap.so.client.exception.ExceptionBuilder;
82 import org.onap.so.client.orchestration.AAIEntityNotFoundException;
83 import org.onap.so.db.catalog.beans.VfModuleCustomization;
84 import org.onap.so.db.catalog.beans.macro.NorthBoundRequest;
85 import org.onap.so.db.catalog.beans.macro.OrchestrationFlow;
86 import org.onap.so.db.catalog.client.CatalogDbClient;
87 import org.onap.so.serviceinstancebeans.CloudConfiguration;
88 import org.onap.so.serviceinstancebeans.ModelInfo;
89 import org.onap.so.serviceinstancebeans.ModelType;
90 import org.onap.so.serviceinstancebeans.RelatedInstance;
91 import org.onap.so.serviceinstancebeans.RelatedInstanceList;
92 import org.onap.so.serviceinstancebeans.RequestDetails;
93 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
94 import org.slf4j.Logger;
95 import org.slf4j.LoggerFactory;
96 import org.springframework.beans.factory.annotation.Autowired;
97 import org.springframework.core.env.Environment;
98 import org.springframework.stereotype.Component;
99 import org.springframework.util.CollectionUtils;
100 import com.fasterxml.jackson.databind.ObjectMapper;
101 import org.onap.so.serviceinstancebeans.InstanceDirection;
102
103 @Component
104 public class WorkflowAction {
105
106     private static final Logger logger = LoggerFactory.getLogger(WorkflowAction.class);
107
108     private static final String SERVICE_INSTANCES = "serviceInstances";
109     private static final String VF_MODULES = "vfModules";
110     private static final String VNF_TYPE = "vnfType";
111     private static final String CONFIGURATION = "Configuration";
112     private static final String SUPPORTEDTYPES =
113             "vnfs|vfModules|networks|networkCollections|volumeGroups|serviceInstances|instanceGroups";
114     private static final String HOMINGSOLUTION = "Homing_Solution";
115     private static final String SERVICE_TYPE_TRANSPORT = "TRANSPORT";
116     private static final String SERVICE_TYPE_BONDING = "BONDING";
117     private static final String CLOUD_OWNER = "DEFAULT";
118     private static final String CREATENETWORKBB = "CreateNetworkBB";
119     private static final String ACTIVATENETWORKBB = "ActivateNetworkBB";
120     private static final String VOLUMEGROUP_DELETE_PATTERN = "(Un|De)(.*)Volume(.*)";
121     private static final String VOLUMEGROUP_CREATE_PATTERN = "(A|C)(.*)Volume(.*)";
122     private static final String DEFAULT_CLOUD_OWNER = "org.onap.so.cloud-owner";
123     private static final String HOMING = "homing";
124
125     @Autowired
126     protected BBInputSetup bbInputSetup;
127     @Autowired
128     protected BBInputSetupUtils bbInputSetupUtils;
129     @Autowired
130     private ExceptionBuilder exceptionBuilder;
131     @Autowired
132     private CatalogDbClient catalogDbClient;
133     @Autowired
134     private Environment environment;
135     @Autowired
136     private AaiResourceIdValidator aaiResourceIdValidator;
137     @Autowired
138     private ExecuteBuildingBlockBuilder executeBuildingBlockBuilder;
139     @Autowired
140     private VnfEBBLoader vnfEBBLoader;
141     @Autowired
142     private ServiceEBBLoader serviceEBBLoader;
143
144     public void setBbInputSetupUtils(BBInputSetupUtils bbInputSetupUtils) {
145         this.bbInputSetupUtils = bbInputSetupUtils;
146     }
147
148     public void setBbInputSetup(BBInputSetup bbInputSetup) {
149         this.bbInputSetup = bbInputSetup;
150     }
151
152     public void selectExecutionList(DelegateExecution execution) throws Exception {
153         try {
154             fillExecutionDefault(execution);
155             final String bpmnRequest = (String) execution.getVariable(BBConstants.G_BPMN_REQUEST);
156             ServiceInstancesRequest sIRequest =
157                     new ObjectMapper().readValue(bpmnRequest, ServiceInstancesRequest.class);
158
159             final String requestId = (String) execution.getVariable(BBConstants.G_REQUEST_ID);
160
161             String uri = (String) execution.getVariable(BBConstants.G_URI);
162             boolean isResume = isUriResume(uri);
163
164             final boolean isALaCarte = (boolean) execution.getVariable(BBConstants.G_ALACARTE);
165             Resource resource = getResource(bbInputSetupUtils, isResume, isALaCarte, uri, requestId);
166
167             WorkflowResourceIds workflowResourceIds = populateResourceIdsFromApiHandler(execution);
168             RequestDetails requestDetails = sIRequest.getRequestDetails();
169             String requestAction = (String) execution.getVariable(BBConstants.G_ACTION);
170             String resourceId = getResourceId(resource, requestAction, requestDetails, workflowResourceIds);
171             WorkflowType resourceType = resource.getResourceType();
172
173             String serviceInstanceId = getServiceInstanceId(execution, resourceId, resourceType);
174
175             fillExecution(execution, requestDetails.getRequestInfo().getSuppressRollback(), resourceId, resourceType);
176             List<ExecuteBuildingBlock> flowsToExecute;
177             if (isRequestMacroServiceResume(isALaCarte, resourceType, requestAction, serviceInstanceId)) {
178                 String errorMessage = "Could not resume Macro flow. Error loading execution path.";
179                 flowsToExecute = loadExecuteBuildingBlocks(execution, requestId, errorMessage);
180             } else if (isALaCarte && isResume) {
181                 String errorMessage =
182                         "Could not resume request with request Id: " + requestId + ". No flowsToExecute was found";
183                 flowsToExecute = loadExecuteBuildingBlocks(execution, requestId, errorMessage);
184             } else {
185                 String vnfType = (String) execution.getVariable(VNF_TYPE);
186                 String cloudOwner = getCloudOwner(requestDetails.getCloudConfiguration());
187                 List<OrchestrationFlow> orchFlows =
188                         (List<OrchestrationFlow>) execution.getVariable(BBConstants.G_ORCHESTRATION_FLOW);
189                 final String apiVersion = (String) execution.getVariable(BBConstants.G_APIVERSION);
190                 final String serviceType =
191                         Optional.ofNullable((String) execution.getVariable(BBConstants.G_SERVICE_TYPE)).orElse("");
192                 if (isALaCarte) {
193                     flowsToExecute = loadExecuteBuildingBlocksForAlaCarte(orchFlows, execution, requestAction,
194                             resourceType, cloudOwner, serviceType, sIRequest, requestId, workflowResourceIds,
195                             requestDetails, resourceId, vnfType, apiVersion);
196                 } else {
197                     flowsToExecute = loadExecuteBuildingBlocksForMacro(sIRequest, resourceType, requestAction,
198                             execution, serviceInstanceId, resourceId, workflowResourceIds, orchFlows, cloudOwner,
199                             serviceType, requestId, apiVersion, vnfType, requestDetails);
200                 }
201             }
202             // If the user set "Homing_Solution" to "none", disable homing, else if "Homing_Solution" is specified,
203             // enable it.
204             if (sIRequest.getRequestDetails().getRequestParameters() != null
205                     && sIRequest.getRequestDetails().getRequestParameters().getUserParams() != null) {
206                 List<Map<String, Object>> userParams =
207                         sIRequest.getRequestDetails().getRequestParameters().getUserParams();
208                 for (Map<String, Object> params : userParams) {
209                     if (params.containsKey(HOMINGSOLUTION)) {
210                         execution.setVariable(HOMING, !"none".equals(params.get(HOMINGSOLUTION)));
211                     }
212                 }
213             }
214
215             if (CollectionUtils.isEmpty(flowsToExecute)) {
216                 throw new IllegalStateException("Macro did not come up with a valid execution path.");
217             }
218
219             List<String> flowNames = new ArrayList<>();
220             logger.info("List of BuildingBlocks to execute:");
221
222             flowsToExecute.forEach(ebb -> {
223                 logger.info(ebb.getBuildingBlock().getBpmnFlowName());
224                 flowNames.add(ebb.getBuildingBlock().getBpmnFlowName());
225             });
226
227             if (!isResume) {
228                 bbInputSetupUtils.persistFlowExecutionPath(requestId, flowsToExecute);
229             }
230             setExecutionVariables(execution, flowsToExecute, flowNames);
231
232         } catch (Exception ex) {
233             if (!(execution.hasVariable("WorkflowException")
234                     || execution.hasVariable("WorkflowExceptionExceptionMessage"))) {
235                 buildAndThrowException(execution, "Exception while setting execution list. ", ex);
236             } else {
237                 throw ex;
238             }
239         }
240     }
241
242     private List<ExecuteBuildingBlock> loadExecuteBuildingBlocksForAlaCarte(List<OrchestrationFlow> orchFlows,
243             DelegateExecution execution, String requestAction, WorkflowType resourceType, String cloudOwner,
244             String serviceType, ServiceInstancesRequest sIRequest, String requestId,
245             WorkflowResourceIds workflowResourceIds, RequestDetails requestDetails, String resourceId, String vnfType,
246             String apiVersion) throws Exception {
247         List<ExecuteBuildingBlock> flowsToExecute = new ArrayList<>();
248         if (orchFlows == null || orchFlows.isEmpty()) {
249             orchFlows = queryNorthBoundRequestCatalogDb(execution, requestAction, resourceType, true, cloudOwner,
250                     serviceType);
251         }
252         Resource resourceKey = getResourceKey(sIRequest, resourceType);
253
254         ReplaceInstanceRelatedInformation replaceInfo = new ReplaceInstanceRelatedInformation();
255         if ((requestAction.equalsIgnoreCase(REPLACEINSTANCE)
256                 || requestAction.equalsIgnoreCase(REPLACEINSTANCERETAINASSIGNMENTS))
257                 && resourceType.equals(WorkflowType.VFMODULE)) {
258             logger.debug("Build a BB list for replacing BB modules");
259             ConfigBuildingBlocksDataObject cbbdo = createConfigBuildingBlocksDataObject(execution, sIRequest, requestId,
260                     workflowResourceIds, requestDetails, requestAction, resourceId, vnfType, orchFlows, apiVersion,
261                     resourceKey, replaceInfo);
262             orchFlows = getVfModuleReplaceBuildingBlocks(cbbdo);
263
264             createBuildingBlocksForOrchFlows(execution, sIRequest, requestId, workflowResourceIds, requestDetails,
265                     requestAction, resourceId, flowsToExecute, vnfType, orchFlows, apiVersion, resourceKey,
266                     replaceInfo);
267         } else {
268             if (isConfiguration(orchFlows) && !requestAction.equalsIgnoreCase(CREATE_INSTANCE)) {
269                 addConfigBuildingBlocksToFlowsToExecuteList(execution, sIRequest, requestId, workflowResourceIds,
270                         requestDetails, requestAction, resourceId, flowsToExecute, vnfType, apiVersion, resourceKey,
271                         replaceInfo, orchFlows);
272             }
273             orchFlows = orchFlows.stream().filter(item -> !item.getFlowName().contains(FABRIC_CONFIGURATION))
274                     .collect(Collectors.toList());
275
276             for (OrchestrationFlow orchFlow : orchFlows) {
277                 ExecuteBuildingBlock ebb = executeBuildingBlockBuilder.buildExecuteBuildingBlock(orchFlow, requestId,
278                         resourceKey, apiVersion, resourceId, requestAction, true, vnfType, workflowResourceIds,
279                         requestDetails, false, null, null, false, replaceInfo);
280                 flowsToExecute.add(ebb);
281             }
282         }
283         return flowsToExecute;
284     }
285
286     private List<ExecuteBuildingBlock> loadExecuteBuildingBlocksForMacro(ServiceInstancesRequest sIRequest,
287             WorkflowType resourceType, String requestAction, DelegateExecution execution, String serviceInstanceId,
288             String resourceId, WorkflowResourceIds workflowResourceIds, List<OrchestrationFlow> orchFlows,
289             String cloudOwner, String serviceType, String requestId, String apiVersion, String vnfType,
290             RequestDetails requestDetails) throws IOException, VrfBondingServiceException {
291         List<ExecuteBuildingBlock> flowsToExecute;
292         List<Resource> resourceList = new ArrayList<>();
293         List<Pair<WorkflowType, String>> aaiResourceIds = new ArrayList<>();
294
295         if (resourceType == WorkflowType.SERVICE || isVNFCreate(resourceType, requestAction)) {
296             resourceList = serviceEBBLoader.getResourceListForService(sIRequest, requestAction, execution,
297                     serviceInstanceId, resourceId, aaiResourceIds);
298         } else if (resourceType == WorkflowType.VNF
299                 && (DELETE_INSTANCE.equalsIgnoreCase(requestAction) || REPLACEINSTANCE.equalsIgnoreCase(requestAction)
300                         || (RECREATE_INSTANCE.equalsIgnoreCase(requestAction)))) {
301             vnfEBBLoader.traverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
302                     workflowResourceIds.getVnfId(), aaiResourceIds);
303         } else if (resourceType == WorkflowType.VNF && UPDATE_INSTANCE.equalsIgnoreCase(requestAction)) {
304             vnfEBBLoader.customTraverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
305                     workflowResourceIds.getVnfId(), aaiResourceIds);
306         } else if (resourceType == WorkflowType.VNF && HEALTH_CHECK.equalsIgnoreCase(requestAction)) {
307             vnfEBBLoader.customTraverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
308                     workflowResourceIds.getVnfId(), aaiResourceIds);
309         } else {
310             buildAndThrowException(execution, "Current Macro Request is not supported");
311         }
312         StringBuilder foundObjects = new StringBuilder();
313         for (WorkflowType type : WorkflowType.values()) {
314             foundObjects.append(type).append(" - ")
315                     .append((int) resourceList.stream().filter(x -> type.equals(x.getResourceType())).count())
316                     .append("    ");
317         }
318         logger.info("Found {}", foundObjects);
319
320         if (orchFlows == null || orchFlows.isEmpty()) {
321             orchFlows = queryNorthBoundRequestCatalogDb(execution, requestAction, resourceType, false, cloudOwner,
322                     serviceType);
323         }
324         boolean vnfReplace = false;
325         if (resourceType.equals(WorkflowType.VNF) && (REPLACEINSTANCE.equalsIgnoreCase(requestAction)
326                 || REPLACEINSTANCERETAINASSIGNMENTS.equalsIgnoreCase(requestAction))) {
327             vnfReplace = true;
328         }
329         flowsToExecute = executeBuildingBlockBuilder.buildExecuteBuildingBlockList(orchFlows, resourceList, requestId,
330                 apiVersion, resourceId, requestAction, vnfType, workflowResourceIds, requestDetails, vnfReplace);
331         if (serviceEBBLoader.isNetworkCollectionInTheResourceList(resourceList)) {
332             logger.info("Sorting for Vlan Tagging");
333             flowsToExecute = sortExecutionPathByObjectForVlanTagging(flowsToExecute, requestAction);
334         }
335         logger.info("Building Block Execution Order");
336         for (ExecuteBuildingBlock block : flowsToExecute) {
337             Resource res = resourceList.stream()
338                     .filter(resource -> resource.getResourceId() == block.getBuildingBlock().getKey()).findAny()
339                     .orElse(null);
340             String log = "Block: " + block.getBuildingBlock().getBpmnFlowName();
341             if (res != null) {
342                 log += ", Resource: " + res.getResourceType() + "[" + res.getResourceId() + "]";
343                 log += ", Priority: " + res.getProcessingPriority();
344                 if (res.getResourceType() == WorkflowType.VFMODULE)
345                     log += ", Base: " + res.isBaseVfModule();
346             }
347             if (block.getBuildingBlock().getBpmnScope() != null)
348                 log += ", Scope: " + block.getBuildingBlock().getBpmnScope();
349             if (block.getBuildingBlock().getBpmnAction() != null)
350                 log += ", Action: " + block.getBuildingBlock().getBpmnAction();
351             logger.info(log);
352         }
353
354         RelatedInstanceList[] instanceList = sIRequest.getRequestDetails().getRelatedInstanceList();
355         execution.setVariable(IS_CHILD_PROCESS, Boolean.FALSE);
356         if (instanceList != null) {
357             for (RelatedInstanceList relatedInstanceList : instanceList) {
358                 RelatedInstance relatedInstance = relatedInstanceList.getRelatedInstance();
359                 if (InstanceDirection.source.equals(relatedInstance.getInstanceDirection())) {
360                     execution.setVariable(IS_CHILD_PROCESS, Boolean.TRUE);
361                     execution.setVariable(PARENT_CORRELATION_ID, requestDetails.getRequestInfo().getCorrelator());
362                 }
363             }
364         }
365
366         // By default, enable homing at VNF level for CREATE_INSTANCE and ASSIGNINSTANCE
367         if (resourceType == WorkflowType.SERVICE
368                 && (requestAction.equals(CREATE_INSTANCE) || requestAction.equals(ASSIGN_INSTANCE))
369                 && resourceList.stream().anyMatch(x -> WorkflowType.VNF.equals(x.getResourceType()))) {
370             execution.setVariable(HOMING, true);
371             execution.setVariable("calledHoming", false);
372         }
373         if (resourceType == WorkflowType.SERVICE && (requestAction.equalsIgnoreCase(ASSIGN_INSTANCE)
374                 || requestAction.equalsIgnoreCase(CREATE_INSTANCE))) {
375             generateResourceIds(flowsToExecute, resourceList, serviceInstanceId);
376         } else {
377             updateResourceIdsFromAAITraversal(flowsToExecute, resourceList, aaiResourceIds, serviceInstanceId);
378         }
379         execution.setVariable("resources", resourceList);
380         return flowsToExecute;
381     }
382
383     private boolean isVNFCreate(WorkflowType resourceType, String requestAction) {
384         return resourceType == WorkflowType.VNF && CREATE_INSTANCE.equalsIgnoreCase(requestAction);
385     }
386
387     private void setExecutionVariables(DelegateExecution execution, List<ExecuteBuildingBlock> flowsToExecute,
388             List<String> flowNames) {
389         execution.setVariable("flowNames", flowNames);
390         execution.setVariable(BBConstants.G_CURRENT_SEQUENCE, 0);
391         execution.setVariable("retryCount", 0);
392         execution.setVariable("isRollback", false);
393         execution.setVariable("flowsToExecute", flowsToExecute);
394         execution.setVariable("isRollbackComplete", false);
395     }
396
397     private List<ExecuteBuildingBlock> loadExecuteBuildingBlocks(DelegateExecution execution, String requestId,
398             String errorMessage) {
399         List<ExecuteBuildingBlock> flowsToExecute;
400         flowsToExecute = bbInputSetupUtils.loadOriginalFlowExecutionPath(requestId);
401         if (flowsToExecute == null) {
402             buildAndThrowException(execution, errorMessage);
403         }
404         return flowsToExecute;
405     }
406
407     private ConfigBuildingBlocksDataObject createConfigBuildingBlocksDataObject(DelegateExecution execution,
408             ServiceInstancesRequest sIRequest, String requestId, WorkflowResourceIds workflowResourceIds,
409             RequestDetails requestDetails, String requestAction, String resourceId, String vnfType,
410             List<OrchestrationFlow> orchFlows, String apiVersion, Resource resourceKey,
411             ReplaceInstanceRelatedInformation replaceInfo) {
412
413         return new ConfigBuildingBlocksDataObject().setsIRequest(sIRequest).setOrchFlows(orchFlows)
414                 .setRequestId(requestId).setResourceKey(resourceKey).setApiVersion(apiVersion).setResourceId(resourceId)
415                 .setRequestAction(requestAction).setaLaCarte(true).setVnfType(vnfType)
416                 .setWorkflowResourceIds(workflowResourceIds).setRequestDetails(requestDetails).setExecution(execution)
417                 .setReplaceInformation(replaceInfo);
418     }
419
420     private void createBuildingBlocksForOrchFlows(DelegateExecution execution, ServiceInstancesRequest sIRequest,
421             String requestId, WorkflowResourceIds workflowResourceIds, RequestDetails requestDetails,
422             String requestAction, String resourceId, List<ExecuteBuildingBlock> flowsToExecute, String vnfType,
423             List<OrchestrationFlow> orchFlows, String apiVersion, Resource resourceKey,
424             ReplaceInstanceRelatedInformation replaceInfo) throws Exception {
425
426         for (OrchestrationFlow orchFlow : orchFlows) {
427             if (orchFlow.getFlowName().contains(CONFIGURATION)) {
428                 List<OrchestrationFlow> configOrchFlows = new ArrayList<>();
429                 configOrchFlows.add(orchFlow);
430                 addConfigBuildingBlocksToFlowsToExecuteList(execution, sIRequest, requestId, workflowResourceIds,
431                         requestDetails, requestAction, resourceId, flowsToExecute, vnfType, apiVersion, resourceKey,
432                         replaceInfo, configOrchFlows);
433             } else {
434                 ExecuteBuildingBlock ebb = executeBuildingBlockBuilder.buildExecuteBuildingBlock(orchFlow, requestId,
435                         resourceKey, apiVersion, resourceId, requestAction, true, vnfType, workflowResourceIds,
436                         requestDetails, false, null, null, false, replaceInfo);
437                 flowsToExecute.add(ebb);
438             }
439         }
440     }
441
442     private void addConfigBuildingBlocksToFlowsToExecuteList(DelegateExecution execution,
443             ServiceInstancesRequest sIRequest, String requestId, WorkflowResourceIds workflowResourceIds,
444             RequestDetails requestDetails, String requestAction, String resourceId,
445             List<ExecuteBuildingBlock> flowsToExecute, String vnfType, String apiVersion, Resource resourceKey,
446             ReplaceInstanceRelatedInformation replaceInfo, List<OrchestrationFlow> configOrchFlows) throws Exception {
447
448         ConfigBuildingBlocksDataObject cbbdo = createConfigBuildingBlocksDataObject(execution, sIRequest, requestId,
449                 workflowResourceIds, requestDetails, requestAction, resourceId, vnfType, configOrchFlows, apiVersion,
450                 resourceKey, replaceInfo);
451         List<ExecuteBuildingBlock> configBuildingBlocks = getConfigBuildingBlocks(cbbdo);
452         flowsToExecute.addAll(configBuildingBlocks);
453     }
454
455     private Resource getResourceKey(ServiceInstancesRequest sIRequest, WorkflowType resourceType) {
456         String resourceId = "";
457         ModelInfo modelInfo = sIRequest.getRequestDetails().getModelInfo();
458         if (modelInfo != null) {
459             if (modelInfo.getModelType().equals(ModelType.service)) {
460                 resourceId = modelInfo.getModelVersionId();
461             } else {
462                 resourceId = modelInfo.getModelCustomizationId();
463             }
464         }
465         return new Resource(resourceType, resourceId, true, null);
466     }
467
468     private String getCloudOwner(CloudConfiguration cloudConfiguration) {
469         if (cloudConfiguration != null && cloudConfiguration.getCloudOwner() != null) {
470             return cloudConfiguration.getCloudOwner();
471         }
472         logger.warn("cloud owner value not found in request details, it will be set as default");
473         return environment.getProperty(DEFAULT_CLOUD_OWNER);
474     }
475
476     protected <T> List<T> getRelatedResourcesInVfModule(String vnfId, String vfModuleId, Class<T> resultClass,
477             AAIObjectName name) {
478         List<T> vnfcs = new ArrayList<>();
479         AAIResourceUri uri =
480                 AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId).vfModule(vfModuleId));
481         AAIResultWrapper vfModuleResultsWrapper = bbInputSetupUtils.getAAIResourceDepthOne(uri);
482         Optional<Relationships> relationshipsOp = vfModuleResultsWrapper.getRelationships();
483         if (relationshipsOp.isEmpty()) {
484             logger.debug("No relationships were found for vfModule in AAI");
485         } else {
486             Relationships relationships = relationshipsOp.get();
487             List<AAIResultWrapper> vnfcResultWrappers = relationships.getByType(name);
488             for (AAIResultWrapper vnfcResultWrapper : vnfcResultWrappers) {
489                 Optional<T> vnfcOp = vnfcResultWrapper.asBean(resultClass);
490                 vnfcOp.ifPresent(vnfcs::add);
491             }
492         }
493         return vnfcs;
494     }
495
496     protected <T> T getRelatedResourcesInVnfc(Vnfc vnfc, Class<T> resultClass, AAIObjectName name)
497             throws VnfcMultipleRelationshipException {
498         T configuration = null;
499         AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().vnfc(vnfc.getVnfcName()));
500         AAIResultWrapper vnfcResultsWrapper = bbInputSetupUtils.getAAIResourceDepthOne(uri);
501         Optional<Relationships> relationshipsOp = vnfcResultsWrapper.getRelationships();
502         if (relationshipsOp.isEmpty()) {
503             logger.debug("No relationships were found for VNFC in AAI");
504         } else {
505             Relationships relationships = relationshipsOp.get();
506             List<AAIResultWrapper> configurationResultWrappers =
507                     this.getResultWrappersFromRelationships(relationships, name);
508             if (configurationResultWrappers.size() > 1) {
509                 throw new VnfcMultipleRelationshipException(vnfc.getVnfcName());
510             }
511             if (!configurationResultWrappers.isEmpty()) {
512                 Optional<T> configurationOp = configurationResultWrappers.get(0).asBean(resultClass);
513                 if (configurationOp.isPresent()) {
514                     configuration = configurationOp.get();
515                 }
516             }
517         }
518         return configuration;
519     }
520
521     protected List<AAIResultWrapper> getResultWrappersFromRelationships(Relationships relationships,
522             AAIObjectName name) {
523         return relationships.getByType(name);
524     }
525
526     protected boolean isConfiguration(List<OrchestrationFlow> orchFlows) {
527         for (OrchestrationFlow flow : orchFlows) {
528             if (flow.getFlowName().contains(CONFIGURATION) && !"ConfigurationScaleOutBB".equals(flow.getFlowName())) {
529                 return true;
530             }
531         }
532         return false;
533     }
534
535     protected List<ExecuteBuildingBlock> getConfigBuildingBlocks(ConfigBuildingBlocksDataObject dataObj)
536             throws AAIEntityNotFoundException, VnfcMultipleRelationshipException {
537
538         List<ExecuteBuildingBlock> flowsToExecuteConfigs = new ArrayList<>();
539         List<OrchestrationFlow> result = dataObj.getOrchFlows().stream()
540                 .filter(item -> item.getFlowName().contains(FABRIC_CONFIGURATION)).collect(Collectors.toList());
541         String vnfId = dataObj.getWorkflowResourceIds().getVnfId();
542         String vfModuleId = dataObj.getWorkflowResourceIds().getVfModuleId();
543
544         String vnfCustomizationUUID = bbInputSetupUtils.getAAIGenericVnf(vnfId).getModelCustomizationId();
545         String vfModuleCustomizationUUID;
546         org.onap.aai.domain.yang.VfModule aaiVfModule = bbInputSetupUtils.getAAIVfModule(vnfId, vfModuleId);
547
548         if (aaiVfModule == null) {
549             logger.error("No matching VfModule is found in Generic-Vnf in AAI for vnfId: {} and vfModuleId : {}", vnfId,
550                     vfModuleId);
551             throw new AAIEntityNotFoundException("No matching VfModule is found in Generic-Vnf in AAI for vnfId: "
552                     + vnfId + " and vfModuleId : " + vfModuleId);
553         } else {
554             vfModuleCustomizationUUID = aaiVfModule.getModelCustomizationId();
555         }
556         String replaceVfModuleCustomizationUUID = "";
557         String replaceVnfModuleCustomizationUUID = "";
558         boolean isReplace = false;
559         if (dataObj.getRequestAction().equalsIgnoreCase("replaceInstance")
560                 || dataObj.getRequestAction().equalsIgnoreCase("replaceInstanceRetainAssignments")) {
561             for (RelatedInstanceList relatedInstList : dataObj.getRequestDetails().getRelatedInstanceList()) {
562                 RelatedInstance relatedInstance = relatedInstList.getRelatedInstance();
563                 if (relatedInstance.getModelInfo().getModelType().equals(ModelType.vnf)) {
564                     replaceVnfModuleCustomizationUUID = relatedInstance.getModelInfo().getModelCustomizationId();
565                 }
566             }
567             replaceVfModuleCustomizationUUID = dataObj.getRequestDetails().getModelInfo().getModelCustomizationId();
568             isReplace = true;
569         }
570
571         List<org.onap.aai.domain.yang.Vnfc> vnfcs =
572                 getRelatedResourcesInVfModule(vnfId, vfModuleId, org.onap.aai.domain.yang.Vnfc.class, Types.VNFC);
573         for (org.onap.aai.domain.yang.Vnfc vnfc : vnfcs) {
574             WorkflowResourceIds workflowIdsCopy = SerializationUtils.clone(dataObj.getWorkflowResourceIds());
575             org.onap.aai.domain.yang.Configuration configuration =
576                     getRelatedResourcesInVnfc(vnfc, org.onap.aai.domain.yang.Configuration.class, Types.CONFIGURATION);
577             if (configuration == null) {
578                 logger.warn(String.format("No configuration found for VNFC %s in AAI", vnfc.getVnfcName()));
579                 continue;
580             }
581             workflowIdsCopy.setConfigurationId(configuration.getConfigurationId());
582             for (OrchestrationFlow orchFlow : result) {
583                 if (!isReplace || (isReplace && (orchFlow.getFlowName().contains("Delete")))) {
584                     if (!isReplace) {
585                         dataObj.getResourceKey().setVfModuleCustomizationId(vfModuleCustomizationUUID);
586                         dataObj.getResourceKey().setVnfCustomizationId(vnfCustomizationUUID);
587                     } else {
588                         if (orchFlow.getFlowName().contains("Delete")) {
589                             dataObj.getResourceKey().setVfModuleCustomizationId(vfModuleCustomizationUUID);
590                             dataObj.getResourceKey().setVnfCustomizationId(vnfCustomizationUUID);
591                         } else {
592                             dataObj.getResourceKey().setVfModuleCustomizationId(replaceVfModuleCustomizationUUID);
593                             dataObj.getResourceKey().setVnfCustomizationId(replaceVnfModuleCustomizationUUID);
594                         }
595                     }
596                     dataObj.getResourceKey().setCvnfModuleCustomizationId(vnfc.getModelCustomizationId());
597                     String vnfcName = vnfc.getVnfcName();
598                     if (vnfcName == null || vnfcName.isEmpty()) {
599                         buildAndThrowException(dataObj.getExecution(), "Exception in create execution list "
600                                 + ": VnfcName does not exist or is null while there is a configuration for the vfModule",
601                                 new Exception("Vnfc and Configuration do not match"));
602                     }
603                     ExecuteBuildingBlock ebb =
604                             executeBuildingBlockBuilder.buildExecuteBuildingBlock(orchFlow, dataObj.getRequestId(),
605                                     dataObj.getResourceKey(), dataObj.getApiVersion(), dataObj.getResourceId(),
606                                     dataObj.getRequestAction(), dataObj.isaLaCarte(), dataObj.getVnfType(),
607                                     workflowIdsCopy, dataObj.getRequestDetails(), false, null, vnfcName, true, null);
608                     flowsToExecuteConfigs.add(ebb);
609                 }
610             }
611         }
612         return flowsToExecuteConfigs;
613     }
614
615     protected void buildAndThrowException(DelegateExecution execution, String msg) {
616         logger.error(msg);
617         execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, msg);
618         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg);
619     }
620
621     protected void buildAndThrowException(DelegateExecution execution, String msg, Exception ex) {
622         logger.error(msg, ex);
623         execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, msg + ex.getMessage());
624         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg + ex.getMessage());
625     }
626
627     protected List<OrchestrationFlow> getVfModuleReplaceBuildingBlocks(ConfigBuildingBlocksDataObject dataObj)
628             throws Exception {
629
630         String vnfId = dataObj.getWorkflowResourceIds().getVnfId();
631         String vfModuleId = dataObj.getWorkflowResourceIds().getVfModuleId();
632
633         logger.debug("BUILDING REPLACE LIST");
634
635         boolean volumeGroupExisted = false;
636         boolean volumeGroupWillExist = false;
637         boolean keepVolumeGroup = false;
638
639         boolean rebuildVolumeGroups = false;
640         if (dataObj.getRequestDetails().getRequestParameters() != null
641                 && dataObj.getRequestDetails().getRequestParameters().getRebuildVolumeGroups() != null) {
642             rebuildVolumeGroups = dataObj.getRequestDetails().getRequestParameters().getRebuildVolumeGroups();
643         }
644         String volumeGroupName = "";
645         Optional<VolumeGroup> volumeGroupFromVfModule =
646                 bbInputSetupUtils.getRelatedVolumeGroupFromVfModule(vnfId, vfModuleId);
647         if (volumeGroupFromVfModule.isPresent()) {
648             String volumeGroupId = volumeGroupFromVfModule.get().getVolumeGroupId();
649             volumeGroupName = volumeGroupFromVfModule.get().getVolumeGroupName();
650             logger.debug("Volume group id of the existing volume group is: {}", volumeGroupId);
651             volumeGroupExisted = true;
652             dataObj.getWorkflowResourceIds().setVolumeGroupId(volumeGroupId);
653             dataObj.getReplaceInformation().setOldVolumeGroupName(volumeGroupName);
654         }
655
656         List<OrchestrationFlow> orchFlows = dataObj.getOrchFlows();
657         VfModuleCustomization vfModuleCustomization = catalogDbClient.getVfModuleCustomizationByModelCuztomizationUUID(
658                 dataObj.getRequestDetails().getModelInfo().getModelCustomizationUuid());
659         if (vfModuleCustomization != null && vfModuleCustomization.getVfModule() != null
660                 && vfModuleCustomization.getVfModule().getVolumeHeatTemplate() != null
661                 && vfModuleCustomization.getVolumeHeatEnv() != null) {
662             volumeGroupWillExist = true;
663             if (!volumeGroupExisted) {
664                 String newVolumeGroupId = UUID.randomUUID().toString();
665                 dataObj.getWorkflowResourceIds().setVolumeGroupId(newVolumeGroupId);
666                 dataObj.getReplaceInformation().setOldVolumeGroupName(volumeGroupName);
667                 logger.debug("newVolumeGroupId: {}", newVolumeGroupId);
668             }
669         }
670
671         if (volumeGroupExisted && volumeGroupWillExist && !rebuildVolumeGroups) {
672             keepVolumeGroup = true;
673         }
674
675         if (!volumeGroupExisted || keepVolumeGroup) {
676             logger.debug("Filtering out deletion of volume groups");
677             orchFlows = orchFlows.stream().filter(item -> !item.getFlowName().matches(VOLUMEGROUP_DELETE_PATTERN))
678                     .collect(Collectors.toList());
679         }
680         if (!volumeGroupWillExist || keepVolumeGroup) {
681             logger.debug("Filtering out creation of volume groups");
682             orchFlows = orchFlows.stream().filter(item -> !item.getFlowName().matches(VOLUMEGROUP_CREATE_PATTERN))
683                     .collect(Collectors.toList());
684         }
685
686         return orchFlows;
687     }
688
689     private void updateResourceIdsFromAAITraversal(List<ExecuteBuildingBlock> flowsToExecute,
690             List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds, String serviceInstanceId) {
691         for (Pair<WorkflowType, String> pair : aaiResourceIds) {
692             logger.debug("{}, {}", pair.getValue0(), pair.getValue1());
693         }
694         Map<Resource, String> resourceInstanceIds = new HashMap<>();
695         Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE))
696                 .forEach(type -> resourceList.stream().filter(resource -> type.equals(resource.getResourceType()))
697                         .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource,
698                                 retrieveAAIResourceId(aaiResourceIds, type), null, serviceInstanceId,
699                                 resourceInstanceIds)));
700     }
701
702     private String retrieveAAIResourceId(List<Pair<WorkflowType, String>> aaiResourceIds, WorkflowType resource) {
703         String id = null;
704         for (int i = 0; i < aaiResourceIds.size(); i++) {
705             if (aaiResourceIds.get(i).getValue0() == resource) {
706                 id = aaiResourceIds.get(i).getValue1();
707                 aaiResourceIds.remove(i);
708                 break;
709             }
710         }
711         return id;
712     }
713
714     private void generateResourceIds(List<ExecuteBuildingBlock> flowsToExecute, List<Resource> resourceList,
715             String serviceInstanceId) {
716         Map<Resource, String> resourceInstanceIds = new HashMap<>();
717         Arrays.stream(WorkflowType.values())
718                 .forEach(type -> resourceList.stream()
719                         .filter(resource -> resource.hasParent() && type.equals(resource.getResourceType()))
720                         .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource, null,
721                                 resource.getVirtualLinkKey(), serviceInstanceId, resourceInstanceIds)));
722     }
723
724     protected void updateWorkflowResourceIds(List<ExecuteBuildingBlock> flowsToExecute, WorkflowType resourceType,
725             Resource resource, String id, String virtualLinkKey, String serviceInstanceId,
726             Map<Resource, String> resourceInstanceIds) {
727         String key = resource.getResourceId();
728         String resourceId = id;
729         if (resourceId == null) {
730             resourceId = UUID.randomUUID().toString();
731         }
732         resourceInstanceIds.put(resource, resourceId);
733         Set<String> assignedFlows = new LinkedHashSet<>();
734         for (ExecuteBuildingBlock ebb : flowsToExecute) {
735             String resourceTypeStr = resourceType.toString();
736             String flowName = ebb.getBuildingBlock().getBpmnFlowName();
737             String scope = StringUtils.defaultString(ebb.getBuildingBlock().getBpmnScope());
738             String action = StringUtils.defaultString(ebb.getBuildingBlock().getBpmnAction());
739
740             if (key != null && key.equalsIgnoreCase(ebb.getBuildingBlock().getKey())
741                     && isFlowAssignable(assignedFlows, ebb, resourceType, flowName + action)
742                     && (flowName.contains(resourceTypeStr)
743                             || (flowName.contains(CONTROLLER) && resourceTypeStr.equalsIgnoreCase(scope)))) {
744                 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
745                 workflowResourceIds.setServiceInstanceId(serviceInstanceId);
746                 Resource parent = resource.getParent();
747                 if (resource.hasParent() && resourceInstanceIds.containsKey(parent)) {
748                     WorkflowResourceIdsUtils.setResourceIdByWorkflowType(workflowResourceIds, parent.getResourceType(),
749                             resourceInstanceIds.get(parent));
750                 }
751                 if (resource.hasParent() && WorkflowType.SERVICE.equals(resourceType)
752                         && WorkflowType.SERVICE.equals(parent.getResourceType())) {
753                     workflowResourceIds.setChildServiceInstanceId(resourceId);
754                     workflowResourceIds.setChildServiceInstanceName(resource.getInstanceName());
755                 } else {
756                     WorkflowResourceIdsUtils.setInstanceNameByWorkflowType(workflowResourceIds, resourceType,
757                             resource.getInstanceName());
758                     WorkflowResourceIdsUtils.setResourceIdByWorkflowType(workflowResourceIds, resourceType, resourceId);
759                 }
760                 ebb.setWorkflowResourceIds(workflowResourceIds);
761                 assignedFlows.add(flowName + action);
762             }
763             if (virtualLinkKey != null && ebb.getBuildingBlock().isVirtualLink()
764                     && virtualLinkKey.equalsIgnoreCase(ebb.getBuildingBlock().getVirtualLinkKey())) {
765                 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
766                 workflowResourceIds.setServiceInstanceId(serviceInstanceId);
767                 workflowResourceIds.setNetworkId(resourceId);
768                 ebb.setWorkflowResourceIds(workflowResourceIds);
769             }
770         }
771     }
772
773     private boolean isFlowAssignable(Set<String> assignedFlows, ExecuteBuildingBlock ebb, WorkflowType resourceType,
774             String assignedFlowName) {
775         String id = WorkflowType.SERVICE.equals(resourceType)
776                 ? StringUtils.defaultString(ebb.getWorkflowResourceIds().getChildServiceInstanceId())
777                 : WorkflowResourceIdsUtils.getResourceIdByWorkflowType(ebb.getWorkflowResourceIds(), resourceType);
778         return !assignedFlows.contains(assignedFlowName) && id.isEmpty();
779     }
780
781     protected WorkflowResourceIds populateResourceIdsFromApiHandler(DelegateExecution execution) {
782         return WorkflowResourceIdsUtils.getWorkflowResourceIdsFromExecution(execution);
783     }
784
785     protected Resource extractResourceIdAndTypeFromUri(String uri) {
786         Pattern patt = Pattern.compile("[vV]\\d+.*?(?:(?:/(?<type>" + SUPPORTEDTYPES
787                 + ")(?:/(?<id>[^/]+))?)(?:/(?<action>[^/]+))?(?:/resume)?)?$");
788         Matcher m = patt.matcher(uri);
789         boolean generated = false;
790
791         if (m.find()) {
792             logger.debug("found match on {} : {} ", uri, m);
793             String type = m.group("type");
794             String id = m.group("id");
795             String action = m.group("action");
796             if (type == null) {
797                 throw new IllegalArgumentException("Uri could not be parsed. No type found. " + uri);
798             }
799             if (action == null) {
800                 if (type.equals(SERVICE_INSTANCES) && (id == null || "assign".equals(id))) {
801                     id = UUID.randomUUID().toString();
802                     generated = true;
803                 } else if (type.equals(VF_MODULES) && "scaleOut".equals(id)) {
804                     id = UUID.randomUUID().toString();
805                     generated = true;
806                 }
807             } else {
808                 if (action.matches(SUPPORTEDTYPES)) {
809                     id = UUID.randomUUID().toString();
810                     generated = true;
811                     type = action;
812                 }
813             }
814             return new Resource(WorkflowType.fromString(convertTypeFromPlural(type)), id, generated, null);
815         } else {
816             throw new IllegalArgumentException("Uri could not be parsed: " + uri);
817         }
818     }
819
820     protected String convertTypeFromPlural(String type) {
821         if (!type.matches(SUPPORTEDTYPES)) {
822             return type;
823         } else {
824             if (type.equals(SERVICE_INSTANCES)) {
825                 return SERVICE;
826             } else {
827                 return type.substring(0, 1).toUpperCase() + type.substring(1, type.length() - 1);
828             }
829         }
830     }
831
832     protected List<ExecuteBuildingBlock> sortExecutionPathByObjectForVlanTagging(List<ExecuteBuildingBlock> orchFlows,
833             String requestAction) {
834         List<ExecuteBuildingBlock> sortedOrchFlows = new ArrayList<>();
835         if (requestAction.equals(CREATE_INSTANCE)) {
836             for (ExecuteBuildingBlock ebb : orchFlows) {
837                 if (ebb.getBuildingBlock().getBpmnFlowName().equals("AssignNetworkBB")) {
838                     String key = ebb.getBuildingBlock().getKey();
839                     boolean isVirtualLink = Boolean.TRUE.equals(ebb.getBuildingBlock().isVirtualLink());
840                     String virtualLinkKey = ebb.getBuildingBlock().getVirtualLinkKey();
841                     sortedOrchFlows.add(ebb);
842                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
843                         if (!isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
844                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
845                             sortedOrchFlows.add(ebb2);
846                             break;
847                         }
848                         if (isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
849                                 && ebb2.getBuildingBlock().getVirtualLinkKey().equalsIgnoreCase(virtualLinkKey)) {
850                             sortedOrchFlows.add(ebb2);
851                             break;
852                         }
853                     }
854                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
855                         if (!isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)
856                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
857                             sortedOrchFlows.add(ebb2);
858                             break;
859                         }
860                         if (isVirtualLink && ebb2.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)
861                                 && ebb2.getBuildingBlock().getVirtualLinkKey().equalsIgnoreCase(virtualLinkKey)) {
862                             sortedOrchFlows.add(ebb2);
863                             break;
864                         }
865                     }
866                 } else if (ebb.getBuildingBlock().getBpmnFlowName().equals(CREATENETWORKBB)
867                         || ebb.getBuildingBlock().getBpmnFlowName().equals(ACTIVATENETWORKBB)) {
868                     continue;
869                 } else if (!"".equals(ebb.getBuildingBlock().getBpmnFlowName())) {
870                     sortedOrchFlows.add(ebb);
871                 }
872             }
873         } else if (requestAction.equals("deleteInstance")) {
874             for (ExecuteBuildingBlock ebb : orchFlows) {
875                 if (ebb.getBuildingBlock().getBpmnFlowName().equals("DeactivateNetworkBB")) {
876                     sortedOrchFlows.add(ebb);
877                     String key = ebb.getBuildingBlock().getKey();
878                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
879                         if (ebb2.getBuildingBlock().getBpmnFlowName().equals("DeleteNetworkBB")
880                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
881                             sortedOrchFlows.add(ebb2);
882                             break;
883                         }
884                     }
885                     for (ExecuteBuildingBlock ebb2 : orchFlows) {
886                         if (ebb2.getBuildingBlock().getBpmnFlowName().equals("UnassignNetworkBB")
887                                 && ebb2.getBuildingBlock().getKey().equalsIgnoreCase(key)) {
888                             sortedOrchFlows.add(ebb2);
889                             break;
890                         }
891                     }
892                 } else if (ebb.getBuildingBlock().getBpmnFlowName().equals("DeleteNetworkBB")
893                         || ebb.getBuildingBlock().getBpmnFlowName().equals("UnassignNetworkBB")) {
894                     continue;
895                 } else if (!ebb.getBuildingBlock().getBpmnFlowName().equals("")) {
896                     sortedOrchFlows.add(ebb);
897                 }
898             }
899         }
900         return sortedOrchFlows;
901     }
902
903     protected List<OrchestrationFlow> queryNorthBoundRequestCatalogDb(DelegateExecution execution, String requestAction,
904             WorkflowType resourceName, boolean aLaCarte, String cloudOwner) {
905         return this.queryNorthBoundRequestCatalogDb(execution, requestAction, resourceName, aLaCarte, cloudOwner, "");
906     }
907
908     protected List<OrchestrationFlow> queryNorthBoundRequestCatalogDb(DelegateExecution execution, String requestAction,
909             WorkflowType resourceName, boolean aLaCarte, String cloudOwner, String serviceType) {
910         List<OrchestrationFlow> listToExecute = new ArrayList<>();
911         NorthBoundRequest northBoundRequest;
912         if (serviceType.equalsIgnoreCase(SERVICE_TYPE_TRANSPORT)
913                 || serviceType.equalsIgnoreCase(SERVICE_TYPE_BONDING)) {
914             northBoundRequest =
915                     catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwnerAndServiceType(
916                             requestAction, resourceName.toString(), aLaCarte, cloudOwner, serviceType);
917         } else {
918             northBoundRequest = catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwner(
919                     requestAction, resourceName.toString(), aLaCarte, cloudOwner);
920         }
921         if (northBoundRequest == null) {
922             northBoundRequest = catalogDbClient.getNorthBoundRequestByActionAndIsALaCarteAndRequestScopeAndCloudOwner(
923                     requestAction, resourceName.toString(), aLaCarte, CLOUD_OWNER);
924         }
925         if (northBoundRequest == null) {
926             buildAndThrowException(execution, String.format("The request: %s %s %s is not supported by GR_API.",
927                     (aLaCarte ? "AlaCarte" : "Macro"), resourceName, requestAction));
928         } else {
929             if (northBoundRequest.getIsToplevelflow() != null) {
930                 execution.setVariable(BBConstants.G_ISTOPLEVELFLOW, northBoundRequest.getIsToplevelflow());
931             }
932             List<OrchestrationFlow> flows = northBoundRequest.getOrchestrationFlowList();
933             if (flows == null) {
934                 flows = new ArrayList<>();
935             } else {
936                 flows.sort(Comparator.comparingInt(OrchestrationFlow::getSequenceNumber));
937             }
938             for (OrchestrationFlow flow : flows) {
939                 if (!flow.getFlowName().contains("BB") && !flow.getFlowName().contains("Activity")) {
940                     List<OrchestrationFlow> macroQueryFlows =
941                             catalogDbClient.getOrchestrationFlowByAction(flow.getFlowName());
942                     listToExecute.addAll(macroQueryFlows);
943                 } else {
944                     listToExecute.add(flow);
945                 }
946             }
947         }
948         return listToExecute;
949     }
950
951     public void handleRuntimeException(DelegateExecution execution) {
952         StringBuilder wfeExpMsg = new StringBuilder("Runtime error ");
953         String runtimeErrorMessage;
954         try {
955             String javaExpMsg = (String) execution.getVariable("BPMN_javaExpMsg");
956             if (javaExpMsg != null && !javaExpMsg.isEmpty()) {
957                 wfeExpMsg.append(": ").append(javaExpMsg);
958             }
959             runtimeErrorMessage = wfeExpMsg.toString();
960             logger.error(runtimeErrorMessage);
961             execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, runtimeErrorMessage);
962         } catch (Exception e) {
963             logger.error("Runtime error", e);
964             // if runtime message was mulformed
965             runtimeErrorMessage = "Runtime error";
966         }
967         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, runtimeErrorMessage);
968     }
969
970     protected boolean isUriResume(String uri) {
971         return uri.endsWith("/resume");
972     }
973
974     protected boolean isRequestMacroServiceResume(boolean aLaCarte, WorkflowType resourceType, String requestAction,
975             String serviceInstanceId) {
976         return (!aLaCarte && resourceType == WorkflowType.SERVICE
977                 && (requestAction.equalsIgnoreCase(ASSIGN_INSTANCE) || requestAction.equalsIgnoreCase(CREATE_INSTANCE))
978                 && (serviceInstanceId != null && serviceInstanceId.trim().length() > 1)
979                 && (bbInputSetupUtils.getAAIServiceInstanceById(serviceInstanceId) != null));
980     }
981
982     private void fillExecutionDefault(DelegateExecution execution) {
983         execution.setVariable("sentSyncResponse", false);
984         execution.setVariable(HOMING, false);
985         execution.setVariable("calledHoming", false);
986         execution.setVariable(BBConstants.G_ISTOPLEVELFLOW, true);
987     }
988
989     private void fillExecution(DelegateExecution execution, boolean suppressRollback, String resourceId,
990             WorkflowType resourceType) {
991         execution.setVariable("suppressRollback", suppressRollback);
992         execution.setVariable("resourceId", resourceId);
993         execution.setVariable("resourceType", resourceType);
994         execution.setVariable("resourceName", resourceType.toString());
995     }
996
997     private Resource getResource(BBInputSetupUtils bbInputSetupUtils, boolean isResume, boolean alaCarte, String uri,
998             String requestId) {
999         if (!alaCarte && isResume) {
1000             logger.debug("replacing URI {}", uri);
1001             uri = bbInputSetupUtils.loadOriginalInfraActiveRequestById(requestId).getRequestUrl();
1002             logger.debug("for RESUME with original value {}", uri);
1003         }
1004         return extractResourceIdAndTypeFromUri(uri);
1005     }
1006
1007     private String getResourceId(Resource resource, String requestAction, RequestDetails requestDetails,
1008             WorkflowResourceIds workflowResourceIds) throws Exception {
1009         if (resource.isGenerated() && requestAction.equalsIgnoreCase("createInstance")
1010                 && requestDetails.getRequestInfo().getInstanceName() != null) {
1011             return aaiResourceIdValidator.validateResourceIdInAAI(resource.getResourceId(), resource.getResourceType(),
1012                     requestDetails.getRequestInfo().getInstanceName(), requestDetails, workflowResourceIds);
1013         } else {
1014             return resource.getResourceId();
1015         }
1016     }
1017
1018     private String getServiceInstanceId(DelegateExecution execution, String resourceId, WorkflowType resourceType) {
1019         String serviceInstanceId = (String) execution.getVariable("serviceInstanceId");
1020         if ((serviceInstanceId == null || serviceInstanceId.isEmpty()) && WorkflowType.SERVICE.equals(resourceType)) {
1021             serviceInstanceId = resourceId;
1022         }
1023         return serviceInstanceId;
1024     }
1025
1026 }