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