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