Implement 'Update Service by importing Tosca Template'-story
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ServiceBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22
23 package org.openecomp.sdc.be.components.impl;
24
25 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
26 import static org.openecomp.sdc.be.components.utils.ConsumptionUtils.handleConsumptionInputMappedToCapabilityProperty;
27 import static org.openecomp.sdc.be.components.utils.ConsumptionUtils.isAssignedValueFromValidType;
28 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName;
29 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToOtherOperationOutput;
30 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.UPDATE_SERVICE_METADATA;
31 import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.SELF;
32 import static org.openecomp.sdc.be.types.ServiceConsumptionSource.SERVICE_INPUT;
33 import static org.openecomp.sdc.be.types.ServiceConsumptionSource.STATIC;
34
35 import com.google.common.annotations.VisibleForTesting;
36 import com.google.common.base.Strings;
37 import com.google.gson.Gson;
38 import com.google.gson.GsonBuilder;
39 import fj.data.Either;
40 import java.nio.charset.StandardCharsets;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.Comparator;
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Map.Entry;
50 import java.util.Objects;
51 import java.util.Optional;
52 import java.util.Set;
53 import java.util.concurrent.Callable;
54 import java.util.function.Function;
55 import java.util.stream.Collectors;
56 import javax.servlet.ServletContext;
57 import javax.servlet.http.HttpServletRequest;
58 import lombok.AccessLevel;
59 import lombok.AllArgsConstructor;
60 import lombok.Getter;
61 import org.apache.commons.collections.CollectionUtils;
62 import org.apache.commons.collections.MapUtils;
63 import org.apache.commons.collections4.ListUtils;
64 import org.apache.commons.lang3.StringUtils;
65 import org.apache.commons.lang3.tuple.ImmutablePair;
66 import org.openecomp.sdc.be.catalog.enums.ChangeTypeEnum;
67 import org.openecomp.sdc.be.components.distribution.engine.IDistributionEngine;
68 import org.openecomp.sdc.be.components.distribution.engine.INotificationData;
69 import org.openecomp.sdc.be.components.distribution.engine.VfModuleArtifactPayload;
70 import org.openecomp.sdc.be.components.health.HealthCheckBusinessLogic;
71 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
72 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
73 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
74 import org.openecomp.sdc.be.components.kafka.KafkaHandler;
75 import org.openecomp.sdc.be.components.path.ForwardingPathValidator;
76 import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
77 import org.openecomp.sdc.be.components.utils.PropertiesUtils;
78 import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation;
79 import org.openecomp.sdc.be.components.validation.component.ComponentContactIdValidator;
80 import org.openecomp.sdc.be.components.validation.component.ComponentDescriptionValidator;
81 import org.openecomp.sdc.be.components.validation.component.ComponentIconValidator;
82 import org.openecomp.sdc.be.components.validation.component.ComponentNameValidator;
83 import org.openecomp.sdc.be.components.validation.component.ComponentProjectCodeValidator;
84 import org.openecomp.sdc.be.components.validation.component.ComponentTagsValidator;
85 import org.openecomp.sdc.be.components.validation.component.ComponentValidator;
86 import org.openecomp.sdc.be.components.validation.service.ServiceCategoryValidator;
87 import org.openecomp.sdc.be.components.validation.service.ServiceFunctionValidator;
88 import org.openecomp.sdc.be.components.validation.service.ServiceInstantiationTypeValidator;
89 import org.openecomp.sdc.be.components.validation.service.ServiceRoleValidator;
90 import org.openecomp.sdc.be.components.validation.service.ServiceTypeValidator;
91 import org.openecomp.sdc.be.components.validation.service.ServiceValidator;
92 import org.openecomp.sdc.be.config.BeEcompErrorManager;
93 import org.openecomp.sdc.be.config.ConfigurationManager;
94 import org.openecomp.sdc.be.dao.api.ActionStatus;
95 import org.openecomp.sdc.be.dao.cassandra.AuditCassandraDao;
96 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
97 import org.openecomp.sdc.be.datamodel.ServiceRelations;
98 import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil;
99 import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter;
100 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
101 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
102 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
103 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
104 import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
105 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
106 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
107 import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType;
108 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
109 import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum;
110 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
111 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
112 import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum;
113 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
114 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
115 import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributionReqInfo;
116 import org.openecomp.sdc.be.impl.ForwardingPathUtils;
117 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
118 import org.openecomp.sdc.be.model.ArtifactDefinition;
119 import org.openecomp.sdc.be.model.CapabilityDefinition;
120 import org.openecomp.sdc.be.model.Component;
121 import org.openecomp.sdc.be.model.ComponentInstance;
122 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
123 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
124 import org.openecomp.sdc.be.model.ComponentParametersView;
125 import org.openecomp.sdc.be.model.DistributionStatusEnum;
126 import org.openecomp.sdc.be.model.GroupInstance;
127 import org.openecomp.sdc.be.model.GroupInstanceProperty;
128 import org.openecomp.sdc.be.model.InputDefinition;
129 import org.openecomp.sdc.be.model.InterfaceDefinition;
130 import org.openecomp.sdc.be.model.LifecycleStateEnum;
131 import org.openecomp.sdc.be.model.Model;
132 import org.openecomp.sdc.be.model.Operation;
133 import org.openecomp.sdc.be.model.PropertyDefinition;
134 import org.openecomp.sdc.be.model.Resource;
135 import org.openecomp.sdc.be.model.Service;
136 import org.openecomp.sdc.be.model.User;
137 import org.openecomp.sdc.be.model.category.CategoryDefinition;
138 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
139 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ForwardingPathOperation;
140 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
141 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
142 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
143 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
144 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
145 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
146 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
147 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
148 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
149 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
150 import org.openecomp.sdc.be.plugins.ServiceCreationPlugin;
151 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
152 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
153 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
154 import org.openecomp.sdc.be.resources.data.auditing.AuditingGenericEvent;
155 import org.openecomp.sdc.be.resources.data.auditing.DistributionDeployEvent;
156 import org.openecomp.sdc.be.resources.data.auditing.DistributionNotificationEvent;
157 import org.openecomp.sdc.be.resources.data.auditing.ResourceAdminEvent;
158 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
159 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo;
160 import org.openecomp.sdc.be.types.ServiceConsumptionData;
161 import org.openecomp.sdc.be.types.ServiceConsumptionSource;
162 import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
163 import org.openecomp.sdc.be.user.Role;
164 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
165 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
166 import org.openecomp.sdc.common.api.Constants;
167 import org.openecomp.sdc.common.datastructure.Wrapper;
168 import org.openecomp.sdc.common.kpi.api.ASDCKpiApi;
169 import org.openecomp.sdc.common.log.wrappers.Logger;
170 import org.openecomp.sdc.common.util.GeneralUtility;
171 import org.openecomp.sdc.common.util.ThreadLocalsHolder;
172 import org.openecomp.sdc.common.util.ValidationUtils;
173 import org.openecomp.sdc.exception.ResponseFormat;
174 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
175 import org.springframework.beans.factory.annotation.Autowired;
176 import org.springframework.http.HttpStatus;
177 import org.springframework.web.context.WebApplicationContext;
178
179 @org.springframework.stereotype.Component("serviceBusinessLogic")
180 public class ServiceBusinessLogic extends ComponentBusinessLogic {
181
182     private static final String IS_VALID = "isValid";
183     private static final String THE_SERVICE_WITH_SYSTEM_NAME_LOCKED = "The service with system name {} locked. ";
184     private static final String FAILED_TO_LOCK_SERVICE_RESPONSE_IS = "Failed to lock service {}. Response is {}. ";
185     private static final String AUDIT_BEFORE_SENDING_RESPONSE = "audit before sending response";
186     private static final Logger log = Logger.getLogger(ServiceBusinessLogic.class);
187     private static final String INITIAL_VERSION = "0.1";
188     private static final String STATUS_SUCCESS_200 = "200";
189     private static final String STATUS_DEPLOYED = "DEPLOYED";
190     private static final String PLACE_HOLDER_RESOURCE_TYPES = "validForResourceTypes";
191     private final IDistributionEngine distributionEngine;
192     private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
193     private final ServiceDistributionValidation serviceDistributionValidation;
194     private final ForwardingPathValidator forwardingPathValidator;
195     private final UiComponentDataConverter uiComponentDataConverter;
196     private final ModelOperation modelOperation;
197     private final ServiceRoleValidator serviceRoleValidator;
198     private final ServiceInstantiationTypeValidator serviceInstantiationTypeValidator;
199     private final ServiceCategoryValidator serviceCategoryValidator;
200     private final ServiceValidator serviceValidator;
201     private final GroupBusinessLogic groupBusinessLogic;
202     private final KafkaHandler kafkaHandler;
203     private ForwardingPathOperation forwardingPathOperation;
204     private AuditCassandraDao auditCassandraDao;
205     private ServiceTypeValidator serviceTypeValidator;
206     private List<ServiceCreationPlugin> serviceCreationPluginList;
207     private ServiceFunctionValidator serviceFunctionValidator;
208
209     public ServiceBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
210                                 IGroupTypeOperation groupTypeOperation, GroupBusinessLogic groupBusinessLogic, InterfaceOperation interfaceOperation,
211                                 InterfaceLifecycleOperation interfaceLifecycleTypeOperation, ArtifactsBusinessLogic artifactsBusinessLogic,
212                                 IDistributionEngine distributionEngine, ComponentInstanceBusinessLogic componentInstanceBusinessLogic,
213                                 ServiceDistributionValidation serviceDistributionValidation, ForwardingPathValidator forwardingPathValidator,
214                                 UiComponentDataConverter uiComponentDataConverter, ArtifactsOperations artifactToscaOperation,
215                                 ComponentContactIdValidator componentContactIdValidator, ComponentNameValidator componentNameValidator,
216                                 ComponentTagsValidator componentTagsValidator, ComponentValidator componentValidator,
217                                 ComponentIconValidator componentIconValidator, ComponentProjectCodeValidator componentProjectCodeValidator,
218                                 ComponentDescriptionValidator componentDescriptionValidator, ModelOperation modelOperation,
219                                 final ServiceRoleValidator serviceRoleValidator,
220                                 final ServiceInstantiationTypeValidator serviceInstantiationTypeValidator,
221                                 final ServiceCategoryValidator serviceCategoryValidator, final ServiceValidator serviceValidator,
222                                 KafkaHandler kafkaHandler) {
223         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, groupBusinessLogic, interfaceOperation,
224             interfaceLifecycleTypeOperation, artifactsBusinessLogic, artifactToscaOperation, componentContactIdValidator, componentNameValidator,
225             componentTagsValidator, componentValidator, componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator);
226         this.distributionEngine = distributionEngine;
227         this.componentInstanceBusinessLogic = componentInstanceBusinessLogic;
228         this.serviceDistributionValidation = serviceDistributionValidation;
229         this.forwardingPathValidator = forwardingPathValidator;
230         this.uiComponentDataConverter = uiComponentDataConverter;
231         this.modelOperation = modelOperation;
232         this.serviceRoleValidator = serviceRoleValidator;
233         this.serviceInstantiationTypeValidator = serviceInstantiationTypeValidator;
234         this.serviceCategoryValidator = serviceCategoryValidator;
235         this.serviceValidator = serviceValidator;
236         this.groupBusinessLogic = groupBusinessLogic;
237         this.kafkaHandler = kafkaHandler;
238     }
239
240     @Autowired
241     public void setServiceTypeValidator(ServiceTypeValidator serviceTypeValidator) {
242         this.serviceTypeValidator = serviceTypeValidator;
243     }
244
245     @Autowired
246     public void setServiceFunctionValidator(ServiceFunctionValidator serviceFunctionValidator) {
247         this.serviceFunctionValidator = serviceFunctionValidator;
248     }
249
250     public Either<List<Map<String, Object>>, ResponseFormat> getComponentAuditRecords(String componentVersion, String componentUUID, String userId) {
251         validateUserExists(userId);
252         Either<List<Map<String, Object>>, ActionStatus> result;
253         try {
254             // Certified Version
255             if (componentVersion.endsWith(".0")) {
256                 Either<List<ResourceAdminEvent>, ActionStatus> eitherAuditingForCertified = auditCassandraDao.getByServiceInstanceId(componentUUID);
257                 if (eitherAuditingForCertified.isLeft()) {
258                     result = Either.left(getAuditingFieldsList(eitherAuditingForCertified.left().value()));
259                 } else {
260                     result = Either.right(eitherAuditingForCertified.right().value());
261                 }
262             }
263             // Uncertified Version
264             else {
265                 result = getAuditRecordsForUncertifiedComponent(componentUUID, componentVersion);
266             }
267         } catch (Exception e) {
268             log.debug("get Audit Records failed with exception {}", e);
269             result = Either.right(ActionStatus.GENERAL_ERROR);
270         }
271         if (result.isRight()) {
272             return Either.right(componentsUtils.getResponseFormat(result.right().value()));
273         } else {
274             return Either.left(result.left().value());
275         }
276     }
277
278     public Either<List<Operation>, ResponseFormat> addServiceConsumptionData(String serviceId, String serviceInstanceId, String operationId,
279                                                                              List<ServiceConsumptionData> serviceConsumptionDataList, String userId) {
280         List<Operation> operationList = new ArrayList<>();
281         Either<Service, StorageOperationStatus> serviceEither = toscaOperationFacade.getToscaElement(serviceId);
282         if (serviceEither.isRight()) {
283             return Either.right(componentsUtils.getResponseFormat(serviceEither.right().value()));
284         }
285         Service service = serviceEither.left().value();
286         StorageOperationStatus storageOperationStatus = graphLockOperation.lockComponent(service.getUniqueId(), NodeTypeEnum.Service);
287         if (storageOperationStatus != StorageOperationStatus.OK) {
288             return Either.right(componentsUtils.getResponseFormat(storageOperationStatus));
289         }
290         try {
291             for (ServiceConsumptionData serviceConsumptionData : serviceConsumptionDataList) {
292                 Either<Operation, ResponseFormat> operationEither = addPropertyServiceConsumption(serviceId, serviceInstanceId, operationId, userId,
293                     serviceConsumptionData);
294                 if (operationEither.isRight()) {
295                     return Either.right(operationEither.right().value());
296                 }
297                 operationList.add(operationEither.left().value());
298             }
299             janusGraphDao.commit();
300             return Either.left(operationList);
301         } catch (Exception e) {
302             janusGraphDao.rollback();
303             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
304         } finally {
305             graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service);
306         }
307     }
308
309     public Either<Operation, ResponseFormat> addPropertyServiceConsumption(String serviceId, String serviceInstanceId, String operationId,
310                                                                            String userId, ServiceConsumptionData serviceConsumptionData) {
311         validateUserExists(userId);
312         Either<Service, StorageOperationStatus> serviceEither = toscaOperationFacade.getToscaElement(serviceId);
313         if (serviceEither.isRight()) {
314             return Either.right(componentsUtils.getResponseFormat(serviceEither.right().value()));
315         }
316         Service parentService = serviceEither.left().value();
317         List<ComponentInstance> componentInstances = parentService.getComponentInstances();
318         if (CollectionUtils.isEmpty(componentInstances)) {
319             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
320         }
321         Optional<ComponentInstance> serviceInstanceCandidate = componentInstances.stream()
322             .filter(instance -> instance.getUniqueId().equals(serviceInstanceId)).findAny();
323         if (!serviceInstanceCandidate.isPresent()) {
324             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
325         }
326         Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces = parentService.getComponentInstancesInterfaces();
327         if (MapUtils.isEmpty(componentInstancesInterfaces)) {
328             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
329         }
330         List<InterfaceDefinition> interfaces = new ArrayList<>();
331         for (ComponentInstanceInterface componentInstanceInterface : componentInstancesInterfaces.get(serviceInstanceId)) {
332             interfaces.add(componentInstanceInterface);
333         }
334         ComponentInstance serviceInstance = serviceInstanceCandidate.get();
335         Optional<InterfaceDefinition> interfaceCandidate = InterfaceOperationUtils.getInterfaceDefinitionFromOperationId(interfaces, operationId);
336         if (!interfaceCandidate.isPresent()) {
337             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
338         }
339         InterfaceDefinition interfaceDefinition = interfaceCandidate.get();
340         Map<String, Operation> operations = interfaceDefinition.getOperationsMap();
341         if (MapUtils.isEmpty(operations)) {
342             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
343         }
344         Operation operation = operations.get(operationId);
345         Either<Operation, ResponseFormat> operationEither = Either.left(operation);
346         ListDataDefinition<OperationInputDefinition> inputs = operation.getInputs();
347         Optional<OperationInputDefinition> inputCandidate = getOperationInputByInputId(serviceConsumptionData, inputs);
348         if (!inputCandidate.isPresent()) {
349             return Either.right(new ResponseFormat(HttpStatus.NOT_FOUND.value()));
350         }
351         OperationInputDefinition operationInputDefinition = inputCandidate.get();
352         // add data to operation
353         if (Objects.nonNull(serviceConsumptionData.getValue())) {
354             operationEither = handleConsumptionValue(parentService, serviceInstanceId, serviceConsumptionData, operation, operationInputDefinition);
355         }
356         if (operationEither.isRight()) {
357             return Either.right(operationEither.right().value());
358         }
359         Operation updatedOperation = operationEither.left().value();
360         operations.remove(operationId);
361         operations.put(operationId, updatedOperation);
362         interfaceDefinition.setOperationsMap(operations);
363         parentService.getComponentInstances().remove(serviceInstance);
364         if (CollectionUtils.isEmpty(parentService.getComponentInstances())) {
365             parentService.setComponentInstances(new ArrayList<>());
366         }
367         Map<String, Object> instanceInterfaces =
368             MapUtils.isEmpty(serviceInstance.getInterfaces()) ? new HashMap<>() : serviceInstance.getInterfaces();
369         instanceInterfaces.remove(interfaceDefinition.getUniqueId());
370         instanceInterfaces.put(interfaceDefinition.getUniqueId(), interfaceDefinition);
371         serviceInstance.setInterfaces(instanceInterfaces);
372         removeComponentInstanceInterfaceByInterfaceId(interfaceDefinition.getUniqueId(), componentInstancesInterfaces.get(serviceInstanceId));
373         componentInstancesInterfaces.get(serviceInstanceId)
374             .add(new ComponentInstanceInterface(interfaceDefinition.getUniqueId(), interfaceDefinition));
375         parentService.getComponentInstances().add(serviceInstance);
376         StorageOperationStatus status = toscaOperationFacade.updateComponentInstanceInterfaces(parentService, serviceInstanceId);
377         if (status != StorageOperationStatus.OK) {
378             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
379         }
380         return Either.left(operation);
381     }
382
383     private void removeComponentInstanceInterfaceByInterfaceId(String interfaceIdToRemove, List<ComponentInstanceInterface> instanceInterfaces) {
384         if (CollectionUtils.isEmpty(instanceInterfaces)) {
385             return;
386         }
387         Optional<ComponentInstanceInterface> interfaceToRemove = instanceInterfaces.stream()
388             .filter(instInterface -> instInterface.getUniqueId().equals(interfaceIdToRemove)).findAny();
389         if (interfaceToRemove.isPresent()) {
390             instanceInterfaces.remove(interfaceToRemove.get());
391         }
392     }
393
394     private Either<Operation, ResponseFormat> handleConsumptionValue(Service containerService, String serviceInstanceId,
395                                                                      ServiceConsumptionData serviceConsumptionData, Operation operation,
396                                                                      OperationInputDefinition operationInputDefinition) {
397         String source = serviceConsumptionData.getSource();
398         String consumptionValue = serviceConsumptionData.getValue();
399         String type = serviceConsumptionData.getType();
400         String operationIdentifier =
401             consumptionValue.contains(".") ? consumptionValue.substring(0, consumptionValue.lastIndexOf('.')) : consumptionValue;
402         ServiceConsumptionSource sourceValue = ServiceConsumptionSource.getSourceValue(source);
403         if (STATIC.equals(sourceValue)) {
404             // Validate constraint on input value
405             Either<Boolean, ResponseFormat> constraintValidationResult = validateOperationInputConstraint(operationInputDefinition, consumptionValue,
406                 type, containerService.getModel());
407             if (constraintValidationResult.isRight()) {
408                 return Either.right(constraintValidationResult.right().value());
409             }
410             return handleConsumptionStaticValue(consumptionValue, type, operation, operationInputDefinition, containerService.getModel());
411         }
412         if (Objects.isNull(sourceValue)) {
413             List<PropertyDefinition> propertyDefinitions;
414             Map<String, List<CapabilityDefinition>> capabilities = null;
415             String componentName;
416             List<OperationOutputDefinition> outputs = null;
417             if (source.equals(containerService.getUniqueId())) {
418                 Either<Service, StorageOperationStatus> serviceToTakePropEither = toscaOperationFacade.getToscaElement(source);
419                 if (serviceToTakePropEither.isRight()) {
420                     return Either.right(componentsUtils.getResponseFormat(serviceToTakePropEither.right().value()));
421                 }
422                 Service service = serviceToTakePropEither.left().value();
423                 operationInputDefinition.setSource(service.getUniqueId());
424                 sourceValue = SERVICE_INPUT;
425                 propertyDefinitions = service.getProperties();
426                 componentName = service.getName();
427                 outputs = InterfaceOperationUtils.getOtherOperationOutputsOfComponent(operationIdentifier, service.getInterfaces())
428                     .getListToscaDataDefinition();
429             } else {
430                 Optional<ComponentInstance> getComponentInstance = containerService.getComponentInstanceById(source);
431                 if (!getComponentInstance.isPresent()) {
432                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, source));
433                 }
434                 ComponentInstance componentInstance = getComponentInstance.get();
435                 operationInputDefinition.setSource(componentInstance.getUniqueId());
436                 propertyDefinitions = componentInstance.getProperties();
437                 capabilities = componentInstance.getCapabilities();
438                 componentName = source.equals(serviceInstanceId) ? SELF : componentInstance.getName();
439                 if (MapUtils.isNotEmpty(componentInstance.getInterfaces())) {
440                     Map<String, InterfaceDataDefinition> componentInstanceInterfaces = componentInstance.getInterfaces().entrySet().stream()
441                         .collect(Collectors.toMap((Map.Entry::getKey), (interfaceEntry -> (InterfaceDataDefinition) interfaceEntry.getValue())));
442                     outputs = InterfaceOperationUtils.getOtherOperationOutputsOfComponent(operationIdentifier, componentInstanceInterfaces)
443                         .getListToscaDataDefinition();
444                 }
445             }
446             if (sourceValue == ServiceConsumptionSource.SERVICE_INPUT) {
447                 //The operation input in service consumption has been mapped to an input in the parent service
448                 return handleConsumptionInputValue(consumptionValue, containerService, operation, operationInputDefinition);
449             }
450             return handleConsumptionPropertyValue(operation, operationInputDefinition, serviceConsumptionData, propertyDefinitions, capabilities,
451                 outputs, componentName);
452         }
453         operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.SOURCE, source);
454         operationInputDefinition.setSource(source);
455         return Either.left(operation);
456     }
457
458     private Optional<OperationInputDefinition> getOperationInputByInputId(ServiceConsumptionData serviceConsumptionData,
459                                                                           ListDataDefinition<OperationInputDefinition> inputs) {
460         if (CollectionUtils.isEmpty(inputs.getListToscaDataDefinition())) {
461             return Optional.empty();
462         }
463         return inputs.getListToscaDataDefinition().stream()
464             .filter(operationInput -> operationInput.getInputId().equals(serviceConsumptionData.getInputId())).findAny();
465     }
466
467     private Either<Operation, ResponseFormat> handleConsumptionPropertyValue(Operation operation, OperationInputDefinition operationInputDefinition,
468                                                                              ServiceConsumptionData serviceConsumptionData,
469                                                                              List<PropertyDefinition> properties,
470                                                                              Map<String, List<CapabilityDefinition>> capabilities,
471                                                                              List<OperationOutputDefinition> outputs, String componentName) {
472         if (CollectionUtils.isEmpty(properties) && CollectionUtils.isEmpty(outputs)) {
473             return Either.left(operation);
474         }
475         String consumptionValue = serviceConsumptionData.getValue();
476         if (CollectionUtils.isNotEmpty(outputs) && isOperationInputMappedToOtherOperationOutput(getOperationOutputName(consumptionValue), outputs)) {
477             return handleConsumptionInputMappedToOperationOutput(operation, operationInputDefinition, outputs, consumptionValue, componentName);
478         }
479         if (CollectionUtils.isNotEmpty(properties) && PropertiesUtils.isNodeProperty(consumptionValue, properties)) {
480             return handleConsumptionInputMappedToProperty(operation, operationInputDefinition, serviceConsumptionData, properties, componentName);
481         }
482         if (MapUtils.isNotEmpty(capabilities)) {
483             return handleConsumptionInputMappedToCapabilityProperty(operation, operationInputDefinition, serviceConsumptionData, capabilities,
484                 componentName);
485         }
486         return Either.left(operation);
487     }
488
489     private Either<Operation, ResponseFormat> handleConsumptionInputMappedToProperty(Operation operation,
490                                                                                      OperationInputDefinition operationInputDefinition,
491                                                                                      ServiceConsumptionData serviceConsumptionData,
492                                                                                      List<PropertyDefinition> properties, String componentName) {
493         Optional<PropertyDefinition> servicePropertyCandidate = properties.stream()
494             .filter(property -> property.getName().equals(serviceConsumptionData.getValue())).findAny();
495         if (servicePropertyCandidate.isPresent()) {
496             boolean isInputTypeSimilarToOperation = isAssignedValueFromValidType(operationInputDefinition.getType(), servicePropertyCandidate.get());
497             if (!isInputTypeSimilarToOperation) {
498                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
499             }
500             addPropertyToInputValue(componentName, operation, operationInputDefinition, servicePropertyCandidate.get());
501         }
502         return Either.left(operation);
503     }
504
505     private Either<Operation, ResponseFormat> handleConsumptionInputMappedToOperationOutput(Operation operation,
506                                                                                             OperationInputDefinition operationInputDefinition,
507                                                                                             List<OperationOutputDefinition> outputs,
508                                                                                             String consumptionValue, String componentName) {
509         String outputName = getOperationOutputName(consumptionValue);
510         Optional<OperationOutputDefinition> servicePropertyOutputCandidate = outputs.stream().filter(output -> output.getName().equals(outputName))
511             .findAny();
512         if (servicePropertyOutputCandidate.isPresent()) {
513             boolean isInputTypeSimilarToOperation = isAssignedValueFromValidType(operationInputDefinition.getType(),
514                 servicePropertyOutputCandidate.get());
515             if (!isInputTypeSimilarToOperation) {
516                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
517             }
518             addOutputToInputValue(componentName, consumptionValue, operation, operationInputDefinition);
519         }
520         return Either.left(operation);
521     }
522
523     private void addPropertyToInputValue(String componentName, Operation operation, OperationInputDefinition operationInputDefinition,
524                                          PropertyDefinition serviceProperty) {
525         Map<String, List<String>> getProperty = new HashMap<>();
526         List<String> getPropertyValues = new ArrayList<>();
527         getPropertyValues.add(componentName);
528         getPropertyValues.add(serviceProperty.getName());
529         getProperty.put(ToscaFunctions.GET_PROPERTY.getFunctionName(), getPropertyValues);
530         operationInputDefinition.setSourceProperty(serviceProperty.getUniqueId());
531         operation.getInputs().delete(operationInputDefinition);
532         operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_PROPERTY, getPropertyValues);
533         operationInputDefinition.setValue((new Gson()).toJson(getProperty));
534         operation.getInputs().add(operationInputDefinition);
535     }
536
537     private void addOutputToInputValue(String componentName, String consumptionValue, Operation operation,
538                                        OperationInputDefinition operationInputDefinition) {
539         Map<String, List<String>> getOperationOutput = InterfaceOperationUtils.createMappedOutputDefaultValue(componentName, consumptionValue);
540         operation.getInputs().delete(operationInputDefinition);
541         operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_OPERATION_OUTPUT, getOperationOutput);
542         operationInputDefinition.setValue((new Gson()).toJson(getOperationOutput));
543         operation.getInputs().add(operationInputDefinition);
544     }
545
546     public Either<Operation, ResponseFormat> handleConsumptionStaticValue(String value, String type, Operation operation,
547                                                                           OperationInputDefinition operationInputDefinition, String model) {
548         boolean isInputTypeSimilarToOperation = isAssignedValueFromValidType(type, value);
549         if (!isInputTypeSimilarToOperation) {
550             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONSUMPTION_TYPE, type));
551         }
552         //Validate Constraint and Value
553         Either<Boolean, ResponseFormat> constraintValidationResponse = validateOperationInputConstraint(operationInputDefinition, value, type, model);
554         if (constraintValidationResponse.isRight()) {
555             return Either.right(constraintValidationResponse.right().value());
556         }
557         addStaticValueToInputOperation(value, operation, operationInputDefinition);
558         return Either.left(operation);
559     }
560
561     private Either<Boolean, ResponseFormat> validateOperationInputConstraint(OperationInputDefinition operationInputDefinition, String value,
562                                                                              String type, String model) {
563         ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty();
564         propertyDefinition.setType(operationInputDefinition.getParentPropertyType());
565         InputDefinition inputDefinition = new InputDefinition();
566         inputDefinition.setDefaultValue(value);
567         inputDefinition.setInputPath(operationInputDefinition.getSubPropertyInputPath());
568         inputDefinition.setType(type);
569         if (Objects.nonNull(operationInputDefinition.getParentPropertyType())) {
570             inputDefinition.setProperties(Collections.singletonList(propertyDefinition));
571         }
572         return new PropertyValueConstraintValidationUtil().validatePropertyConstraints(Collections.singletonList(inputDefinition),
573             applicationDataTypeCache, model);
574     }
575
576     private void addStaticValueToInputOperation(String value, Operation operation, OperationInputDefinition operationInputDefinition) {
577         operation.getInputs().delete(operationInputDefinition);
578         operationInputDefinition.setSource(STATIC.getSource());
579         operationInputDefinition.setSourceProperty(null);
580         operationInputDefinition.setValue(value);
581         operation.getInputs().add(operationInputDefinition);
582     }
583
584     private Either<Operation, ResponseFormat> handleConsumptionInputValue(String inputId, Service service, Operation operation,
585                                                                           OperationInputDefinition operationInputDefinition) {
586         List<InputDefinition> serviceInputs = service.getInputs();
587         Optional<InputDefinition> inputForValue = serviceInputs.stream().filter(input -> input.getUniqueId().contains(inputId)).findAny();
588         if (inputForValue.isPresent()) {
589             boolean isInputTypeSimilarToOperation = isAssignedValueFromValidType(operationInputDefinition.getType(), inputForValue.get());
590             if (!isInputTypeSimilarToOperation) {
591                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
592             }
593             addGetInputValueToOperationInput(operation, operationInputDefinition, inputForValue.get());
594         }
595         return Either.left(operation);
596     }
597
598     private void addGetInputValueToOperationInput(Operation operation, OperationInputDefinition operationInputDefinition,
599                                                   InputDefinition inputForValue) {
600         operation.getInputs().delete(operationInputDefinition);
601         Map<String, String> getInputMap = new HashMap<>();
602         getInputMap.put(ToscaFunctions.GET_INPUT.getFunctionName(), inputForValue.getName());
603         operationInputDefinition.setSourceProperty(inputForValue.getUniqueId());
604         operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_INPUT, getInputMap);
605         operationInputDefinition.setValue(new Gson().toJson(getInputMap));
606         operation.getInputs().add(operationInputDefinition);
607     }
608
609     private Either<List<Map<String, Object>>, ActionStatus> getAuditRecordsForUncertifiedComponent(String componentUUID, String componentVersion) {
610         // First Query
611         Either<List<ResourceAdminEvent>, ActionStatus> eitherprevVerAudit = auditCassandraDao
612             .getAuditByServiceIdAndPrevVersion(componentUUID, componentVersion);
613         if (eitherprevVerAudit.isRight()) {
614             return Either.right(eitherprevVerAudit.right().value());
615         }
616         // Second Query
617         Either<List<ResourceAdminEvent>, ActionStatus> eitherCurrVerAudit = auditCassandraDao
618             .getAuditByServiceIdAndCurrVersion(componentUUID, componentVersion);
619         if (eitherCurrVerAudit.isRight()) {
620             return Either.right(eitherCurrVerAudit.right().value());
621         }
622         Either<List<ResourceAdminEvent>, ActionStatus> eitherArchiveRestoreList = getArchiveRestoreEventList(componentUUID);
623         if (eitherArchiveRestoreList.isRight()) {
624             return Either.right(eitherArchiveRestoreList.right().value());
625         }
626         List<Map<String, Object>> prevVerAuditList = getAuditingFieldsList(eitherprevVerAudit.left().value());
627         List<Map<String, Object>> currVerAuditList = getAuditingFieldsList(eitherCurrVerAudit.left().value());
628         List<Map<String, Object>> duplicateElements = new ArrayList<>();
629         duplicateElements.addAll(prevVerAuditList);
630         duplicateElements.retainAll(currVerAuditList);
631         List<Map<String, Object>> joinedNonDuplicatedList = new ArrayList<>();
632         joinedNonDuplicatedList.addAll(prevVerAuditList);
633         joinedNonDuplicatedList.removeAll(duplicateElements);
634         joinedNonDuplicatedList.addAll(currVerAuditList);
635         joinedNonDuplicatedList.addAll(getAuditingFieldsList(eitherArchiveRestoreList.left().value()));
636         return Either.left(joinedNonDuplicatedList);
637     }
638
639     private Either<List<ResourceAdminEvent>, ActionStatus> getArchiveRestoreEventList(String componentUUID) {
640         // Archive Query
641         Either<List<ResourceAdminEvent>, ActionStatus> eitherArchiveAudit = auditCassandraDao.getArchiveAuditByServiceInstanceId(componentUUID);
642         if (eitherArchiveAudit.isRight()) {
643             return Either.right(eitherArchiveAudit.right().value());
644         }
645         // Restore Query
646         Either<List<ResourceAdminEvent>, ActionStatus> eitherRestoreAudit = auditCassandraDao.getRestoreAuditByServiceInstanceId(componentUUID);
647         if (eitherRestoreAudit.isRight()) {
648             return Either.right(eitherRestoreAudit.right().value());
649         }
650         List<ResourceAdminEvent> archiveAudit = new ArrayList<>();
651         archiveAudit.addAll(eitherArchiveAudit.left().value());
652         archiveAudit.addAll(eitherRestoreAudit.left().value());
653         return Either.left(archiveAudit);
654     }
655
656     private List<Map<String, Object>> getAuditingFieldsList(List<? extends AuditingGenericEvent> prevVerAuditList) {
657         List<Map<String, Object>> prevVerAudit = new ArrayList<>();
658         for (AuditingGenericEvent auditEvent : prevVerAuditList) {
659             auditEvent.fillFields();
660             prevVerAudit.add(auditEvent.getFields());
661         }
662         return prevVerAudit;
663     }
664
665     /**
666      * createService
667      *
668      * @param service - Service
669      * @param user    - modifier data (userId)
670      * @return Either<Service, responseFormat>
671      */
672     public Either<Service, ResponseFormat> createService(Service service, User user) {
673         // get user details
674         user = validateUser(user, "Create Service", service, AuditingActionEnum.CREATE_RESOURCE, false);
675         log.debug("User returned from validation: {}", user);
676         // validate user role
677         validateUserRole(user, service, new ArrayList<>(), AuditingActionEnum.CREATE_RESOURCE, null);
678         service.setCreatorUserId(user.getUserId());
679         // warn on overridden fields
680         checkFieldsForOverideAttempt(service);
681         // enrich object
682         log.debug("enrich service with version and state");
683         service.setState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
684         service.setVersion(INITIAL_VERSION);
685         service.setConformanceLevel(ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel());
686         service.setDistributionStatus(DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED);
687         service.setComponentType(ComponentTypeEnum.SERVICE);
688         Either<Service, ResponseFormat> createServiceResponse = validateServiceBeforeCreate(service, user, AuditingActionEnum.CREATE_RESOURCE);
689         if (createServiceResponse.isRight()) {
690             return createServiceResponse;
691         }
692         return createServiceByDao(service, user).left().bind(c -> updateCatalog(c, ChangeTypeEnum.LIFECYCLE).left().map(Service.class::cast));
693     }
694
695     private void checkFieldsForOverideAttempt(Service service) {
696         checkComponentFieldsForOverrideAttempt(service);
697         if (service.getDistributionStatus() != null) {
698             log.info("Distribution Status cannot be defined by user. This field will be overridden by the application");
699         }
700     }
701
702     private Either<Service, ResponseFormat> createServiceByDao(final Service service, final User user) {
703         log.debug("send service {} to dao for create", service.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
704         Either<Boolean, ResponseFormat> lockResult = lockComponentByName(service.getSystemName(), service, "Create Service");
705         if (lockResult.isRight()) {
706             ResponseFormat responseFormat = lockResult.right().value();
707             componentsUtils.auditComponentAdmin(responseFormat, user, service, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
708             return Either.right(responseFormat);
709         }
710         log.debug("System name locked is {}, status = {}", service.getSystemName(), lockResult);
711         try {
712             createMandatoryArtifactsData(service, user);
713             createServiceApiArtifactsData(service, user);
714             setToscaArtifactsPlaceHolders(service, user);
715
716             if (service.isSubstituteCandidate() || genericTypeBusinessLogic.hasMandatorySubstitutionType(service)) {
717                 final Resource genericType = fetchAndSetDerivedFromGenericType(service);
718                 generatePropertiesFromGenericType(service, genericType);
719                 if (Constants.DEFAULT_MODEL_NAME.equals(service.getModel()) || service.getModel() == null) {
720                     generateAndAddInputsFromGenericTypeProperties(service, genericType);
721                 }
722             }
723             beforeCreate(service);
724             Either<Service, StorageOperationStatus> dataModelResponse = toscaOperationFacade.createToscaComponent(service);
725             if (dataModelResponse.isLeft()) {
726                 log.debug("Service '{}' created successfully", service.getName());
727                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED);
728                 componentsUtils.auditComponentAdmin(responseFormat, user, service, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
729                 ASDCKpiApi.countCreatedServicesKPI();
730                 return Either.left(dataModelResponse.left().value());
731             }
732             janusGraphDao.rollback();
733             ResponseFormat responseFormat = componentsUtils
734                 .getResponseFormatByComponent(componentsUtils.convertFromStorageResponse(dataModelResponse.right().value()), service,
735                     ComponentTypeEnum.SERVICE);
736             log.debug(AUDIT_BEFORE_SENDING_RESPONSE);
737             componentsUtils.auditComponentAdmin(responseFormat, user, service, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
738             return Either.right(responseFormat);
739         } finally {
740             graphLockOperation.unlockComponentByName(service.getSystemName(), service.getUniqueId(), NodeTypeEnum.Service);
741         }
742     }
743
744     private void beforeCreate(final Service service) {
745         if (CollectionUtils.isEmpty(serviceCreationPluginList)) {
746             return;
747         }
748         serviceCreationPluginList.stream().sorted(Comparator.comparingInt(ServiceCreationPlugin::getOrder)).forEach(serviceCreationPlugin -> {
749             try {
750                 serviceCreationPlugin.beforeCreate(service);
751             } catch (final Exception e) {
752                 log.error("An error has occurred while running the serviceCreationPlugin '{}'", serviceCreationPlugin.getClass(), e);
753             }
754         });
755     }
756
757     @SuppressWarnings("unchecked")
758     private void createServiceApiArtifactsData(Service service, User user) {
759         // create mandatory artifacts
760
761         // TODO it must be removed after that artifact uniqueId creation will be
762
763         // moved to ArtifactOperation
764         String serviceUniqueId = service.getUniqueId();
765         Map<String, ArtifactDefinition> artifactMap = service.getServiceApiArtifacts();
766         if (artifactMap == null) {
767             artifactMap = new HashMap<>();
768         }
769         Map<String, Object> serviceApiArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration().getServiceApiArtifacts();
770         List<String> exludeServiceCategory = ConfigurationManager.getConfigurationManager().getConfiguration().getExcludeServiceCategory();
771         List<CategoryDefinition> categories = service.getCategories();
772         boolean isCreateArtifact = true;
773         if (categories != null && exludeServiceCategory != null && !exludeServiceCategory.isEmpty()) {
774             for (String exlude : exludeServiceCategory) {
775                 if (exlude.equalsIgnoreCase(categories.get(0).getName())) {
776                     isCreateArtifact = false;
777                     break;
778                 }
779             }
780         }
781         if (serviceApiArtifacts != null && isCreateArtifact) {
782             Set<String> keys = serviceApiArtifacts.keySet();
783             for (String serviceApiArtifactName : keys) {
784                 Map<String, Object> artifactInfoMap = (Map<String, Object>) serviceApiArtifacts.get(serviceApiArtifactName);
785                 ArtifactDefinition artifactDefinition = createArtifactDefinition(serviceUniqueId, serviceApiArtifactName, artifactInfoMap, user,
786                     true);
787                 artifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.SERVICE_API);
788                 artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition);
789             }
790             service.setServiceApiArtifacts(artifactMap);
791         }
792     }
793
794     @VisibleForTesting
795     protected Either<Service, ResponseFormat> validateServiceBeforeCreate(Service service, User user, AuditingActionEnum actionEnum) {
796         try {
797             serviceValidator.validate(user, service, actionEnum);
798         } catch (ComponentException exp) {
799             ResponseFormat responseFormat = componentsUtils.getResponseFormat(exp);
800             componentsUtils.auditComponentAdmin(responseFormat, user, service, AuditingActionEnum.CREATE_SERVICE, ComponentTypeEnum.SERVICE);
801             throw exp;
802         }
803         if (!AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(actionEnum) &&
804             !AuditingActionEnum.UPDATE_SERVICE_TOSCA_MODEL.equals(actionEnum)) {
805             service.setCreatorFullName(user.getFirstName() + " " + user.getLastName());
806             service.setContactId(service.getContactId().toLowerCase());
807             // Generate invariant UUID - must be here and not in operation since it should stay constant during clone
808             service.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID());
809         }
810         return Either.left(service);
811     }
812
813     public Either<Map<String, Boolean>, ResponseFormat> validateServiceNameExists(String serviceName, String userId) {
814         validateUserExists(userId);
815         Either<Boolean, StorageOperationStatus> dataModelResponse = toscaOperationFacade
816             .validateComponentNameUniqueness(serviceName, null, ComponentTypeEnum.SERVICE);
817         // DE242223
818         janusGraphDao.commit();
819         if (dataModelResponse.isLeft()) {
820             Map<String, Boolean> result = new HashMap<>();
821             result.put(IS_VALID, dataModelResponse.left().value());
822             log.debug("validation was successfully performed.");
823             return Either.left(result);
824         }
825         ResponseFormat responseFormat = componentsUtils
826             .getResponseFormat(componentsUtils.convertFromStorageResponse(dataModelResponse.right().value()));
827         return Either.right(responseFormat);
828     }
829
830     public void setElementDao(IElementOperation elementDao) {
831         this.elementDao = elementDao;
832     }
833
834     @Autowired
835     public void setCassandraAuditingDao(AuditCassandraDao auditingDao) {
836         this.auditCassandraDao = auditingDao;
837     }
838
839     public ArtifactsBusinessLogic getArtifactBl() {
840         return artifactsBusinessLogic;
841     }
842
843     public void setArtifactBl(ArtifactsBusinessLogic artifactBl) {
844         this.artifactsBusinessLogic = artifactBl;
845     }
846
847     public Either<Service, ResponseFormat> updateServiceMetadata(String serviceId, Service serviceUpdate, User user) {
848         user = validateUser(user, "updateServiceMetadata", serviceUpdate, null, false);
849         // validate user role
850         validateUserRole(user, serviceUpdate, new ArrayList<>(), null, null);
851         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(serviceId);
852         if (storageStatus.isRight()) {
853             return Either.right(componentsUtils
854                 .getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), ""));
855         }
856         Service currentService = storageStatus.left().value();
857         if (!ComponentValidationUtils.canWorkOnComponent(currentService, user.getUserId())) {
858             log.info("Restricted operation for user: {}, on service: {}", user.getUserId(), currentService.getCreatorUserId());
859             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
860         }
861         List<String> subNodePropsToBeRemoved = getSubstitutionNodePropertiesToBeRemoved(currentService, serviceUpdate);
862         List<PropertyDefinition> subNodePropsToBeAdded = getSubstitutionNodePropertiesToBeAdded(currentService, serviceUpdate);
863         boolean subNodeChanged = isSubstitutionNodeChanged(currentService, serviceUpdate);
864         Either<Service, ResponseFormat> validationResponse =
865             validateAndUpdateServiceMetadata(user, currentService, serviceUpdate, subNodeChanged, ListUtils.emptyIfNull(subNodePropsToBeRemoved));
866         if (validationResponse.isRight()) {
867             log.info("service update metadata: validations field.");
868             return validationResponse;
869         }
870         Service serviceToUpdate = validationResponse.left().value();
871         // lock resource
872         lockComponent(serviceId, currentService, "Update Service Metadata");
873         try {
874             if (subNodeChanged) {
875                 if (!subNodePropsToBeRemoved.isEmpty()) {
876                     removePropertiesFromService(currentService, subNodePropsToBeRemoved);
877                     removeInputsFromService(currentService, subNodePropsToBeRemoved);
878                 }
879                 if (!subNodePropsToBeAdded.isEmpty()) {
880                     addPropertiesToService(currentService, subNodePropsToBeAdded);
881                     if (Constants.DEFAULT_MODEL_NAME.equals(currentService.getModel()) || currentService.getModel() == null) {
882                         addInputsToService(currentService, subNodePropsToBeAdded);
883                     }
884                 }
885             }
886             return toscaOperationFacade.updateToscaElement(serviceToUpdate).right().map(rf -> {
887                 janusGraphDao.rollback();
888                 BeEcompErrorManager.getInstance().logBeSystemError("Update Service Metadata");
889                 log.debug("failed to update sevice {}", serviceToUpdate.getUniqueId());
890                 return (componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
891             }).left().bind(this::updateCatalogAndCommit);
892         } catch (ComponentException e) {
893             janusGraphDao.rollback();
894             BeEcompErrorManager.getInstance().logBeSystemError("Update Service Metadata");
895             log.debug("failed to update sevice {}", serviceToUpdate.getUniqueId());
896             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
897         } finally {
898             graphLockOperation.unlockComponent(serviceId, NodeTypeEnum.Service);
899         }
900     }
901
902     private Either<Service, ResponseFormat> updateCatalogAndCommit(Service service) {
903         Either<Service, ResponseFormat> res = updateCatalog(service, ChangeTypeEnum.LIFECYCLE).left().map(Service.class::cast);
904         janusGraphDao.commit();
905         return res;
906     }
907
908     public Set<String> deleteForwardingPaths(String serviceId, Set<String> pathIdsToDelete, User user, boolean lock) {
909         Service serviceToDelete = initServiceToDeletePaths(serviceId, pathIdsToDelete);
910         user = validateUser(user, "deleteForwardingPaths", serviceToDelete, null, false);
911         // validate user role
912         validateUserRole(user, serviceToDelete, new ArrayList<>(), null, null);
913         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(serviceId);
914         if (storageStatus.isRight()) {
915             throw new ByActionStatusComponentException(
916                 componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), "");
917         }
918         Service service = storageStatus.left().value();
919         Either<Set<String>, StorageOperationStatus> result = null;
920         if (lock) {
921             try {
922                 lockComponent(service.getUniqueId(), service, "Delete Forwarding Path on Service");
923             } catch (ComponentException e) {
924                 janusGraphDao.rollback();
925                 throw new ByActionStatusComponentException(
926                     componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), "");
927             }
928         }
929         try {
930             result = forwardingPathOperation.deleteForwardingPath(service, pathIdsToDelete);
931             if (result.isRight()) {
932                 log.debug(FAILED_TO_LOCK_SERVICE_RESPONSE_IS, service.getName(), result.right().value());
933                 janusGraphDao.rollback();
934                 throw new ByActionStatusComponentException(
935                     componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE));
936             }
937             janusGraphDao.commit();
938             log.debug(THE_SERVICE_WITH_SYSTEM_NAME_LOCKED, service.getSystemName());
939         } catch (ComponentException e) {
940             log.error("Exception occurred during delete forwarding path : {}", e.getMessage(), e);
941             janusGraphDao.rollback();
942             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
943         } finally {
944             graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service);
945         }
946         return result.left().value();
947     }
948
949     private Service initServiceToDeletePaths(String serviceId, Collection<String> pathIdsToDelete) {
950         Service serviceToDelete = new Service();
951         serviceToDelete.setUniqueId(serviceId);
952         serviceToDelete.setForwardingPaths(new HashMap<>());
953         pathIdsToDelete.forEach(pathIdToDelete -> serviceToDelete.getForwardingPaths().put(pathIdToDelete, new ForwardingPathDataDefinition()));
954         return serviceToDelete;
955     }
956
957     public Service updateForwardingPath(String serviceId, Service serviceUpdate, User user, boolean lock) {
958         return createOrUpdateForwardingPath(serviceId, serviceUpdate, user, true, "updateForwardingPath", lock);
959     }
960
961     public Service createForwardingPath(String serviceId, Service serviceUpdate, User user, boolean lock) {
962         return createOrUpdateForwardingPath(serviceId, serviceUpdate, user, false, "createForwardingPath", lock);
963     }
964
965     private ForwardingPathDataDefinition getTrimmedValues(ForwardingPathDataDefinition path) {
966         ForwardingPathDataDefinition dataDefinition = new ForwardingPathDataDefinition(path.getName());
967         dataDefinition.setName(Strings.nullToEmpty(path.getName()).trim());
968         dataDefinition.setProtocol(Strings.nullToEmpty(path.getProtocol()).trim());
969         dataDefinition.setDestinationPortNumber(Strings.nullToEmpty(path.getDestinationPortNumber()).trim());
970         dataDefinition.setUniqueId(path.getUniqueId());
971         dataDefinition.setPathElements(path.getPathElements());
972         dataDefinition.setDescription(path.getDescription());
973         dataDefinition.setToscaResourceName(path.getToscaResourceName());
974         return dataDefinition;
975     }
976
977     private Service createOrUpdateForwardingPath(String serviceId, Service serviceUpdate, User user, boolean isUpdate, String errorContext,
978                                                  boolean lock) {
979         validateUserAndRole(serviceUpdate, user, errorContext);
980         Map<String, ForwardingPathDataDefinition> forwardingPaths = serviceUpdate.getForwardingPaths();
981         Map<String, ForwardingPathDataDefinition> trimmedForwardingPaths = forwardingPaths.entrySet().stream()
982             .collect(Collectors.toMap(Map.Entry::getKey, entry -> new ForwardingPathDataDefinition(getTrimmedValues(entry.getValue()))));
983         forwardingPathValidator.validateForwardingPaths(trimmedForwardingPaths.values(), serviceId, isUpdate);
984         Either<Service, StorageOperationStatus> serviceStorageOperationStatusEither = toscaOperationFacade.getToscaElement(serviceId);
985         if (serviceStorageOperationStatusEither.isRight()) {
986             StorageOperationStatus errorStatus = serviceStorageOperationStatusEither.right().value();
987             log.debug("Failed to fetch service information by service id, error {}", errorStatus);
988             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(errorStatus));
989         }
990         Service storedService = serviceStorageOperationStatusEither.left().value();
991         Either<ForwardingPathDataDefinition, StorageOperationStatus> result;
992         Component component = getForwardingPathOriginComponent();
993         final String toscaResourceName;
994         if (component.getComponentType() == ComponentTypeEnum.RESOURCE) {
995             toscaResourceName = ((Resource) component).getToscaResourceName();
996         } else {
997             toscaResourceName = "";
998         }
999         if (lock) {
1000             lockComponent(storedService.getUniqueId(), storedService, "Add or Update Forwarding Path on Service");
1001             log.debug(THE_SERVICE_WITH_SYSTEM_NAME_LOCKED, storedService.getSystemName());
1002         }
1003         Map<String, ForwardingPathDataDefinition> resultMap = new HashMap<>();
1004         try {
1005             trimmedForwardingPaths.values().forEach(fp -> fp.setToscaResourceName(toscaResourceName));
1006             populateForwardingPaths(serviceId, isUpdate, trimmedForwardingPaths, resultMap);
1007             janusGraphDao.commit();
1008         } finally {
1009             if (lock) {
1010                 graphLockOperation.unlockComponent(storedService.getUniqueId(), NodeTypeEnum.Service);
1011             }
1012         }
1013         return createServiceWithForwardingPathForResponse(serviceId, resultMap);
1014     }
1015
1016     private Component getForwardingPathOriginComponent() {
1017         Either<Component, StorageOperationStatus> forwardingPathOrigin = toscaOperationFacade
1018             .getLatestByName(ForwardingPathUtils.FORWARDING_PATH_NODE_NAME, null);
1019         if (forwardingPathOrigin.isRight()) {
1020             StorageOperationStatus errorStatus = forwardingPathOrigin.right().value();
1021             log.debug("Failed to fetch normative forwarding path resource by tosca name, error {}", errorStatus);
1022             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(errorStatus));
1023         }
1024         return forwardingPathOrigin.left().value();
1025     }
1026
1027     private void populateForwardingPaths(String serviceId, boolean isUpdate, Map<String, ForwardingPathDataDefinition> trimmedForwardingPaths,
1028                                          Map<String, ForwardingPathDataDefinition> resultMap) {
1029         Either<ForwardingPathDataDefinition, StorageOperationStatus> result;
1030         try {
1031             for (ForwardingPathDataDefinition forwardingPathDataDefinition : trimmedForwardingPaths.values()) {
1032                 if (isUpdate) {
1033                     result = forwardingPathOperation.updateForwardingPath(serviceId, forwardingPathDataDefinition);
1034                 } else {
1035                     result = forwardingPathOperation.addForwardingPath(serviceId, forwardingPathDataDefinition);
1036                 }
1037                 if (result.isRight()) {
1038                     janusGraphDao.rollback();
1039                     throw new ByResponseFormatComponentException(componentsUtils
1040                         .getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value(), ComponentTypeEnum.SERVICE), ""));
1041                 } else {
1042                     ForwardingPathDataDefinition fpDataDefinition = result.left().value();
1043                     resultMap.put(fpDataDefinition.getUniqueId(), forwardingPathDataDefinition);
1044                 }
1045             }
1046         } catch (ComponentException e) {
1047             janusGraphDao.rollback();
1048             log.error("Exception occurred during add or update forwarding path property values: {}", e.getMessage(), e);
1049             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
1050         }
1051     }
1052
1053     private Service createServiceWithForwardingPathForResponse(String serviceId,
1054                                                                Map<String, ForwardingPathDataDefinition> forwardingPathDataDefinitionMap) {
1055         Service service = new Service();
1056         service.setUniqueId(serviceId);
1057         service.setForwardingPaths(forwardingPathDataDefinitionMap);
1058         return service;
1059     }
1060
1061     private void validateUserAndRole(Service serviceUpdate, User user, String errorContext) {
1062         user = validateUser(user, errorContext, serviceUpdate, null, false);
1063         validateUserRole(user, serviceUpdate, new ArrayList<>(), null, null);
1064     }
1065
1066     @VisibleForTesting
1067     Either<Service, ResponseFormat> validateAndUpdateServiceMetadata(User user, Service currentService, Service serviceUpdate, boolean subNodeChanged,
1068                                                                      List<String> subNodePropsToBeRemoved) {
1069         try {
1070             boolean hasBeenCertified = ValidationUtils.hasBeenCertified(currentService.getVersion());
1071             if (subNodeChanged) {
1072                 if (!subNodePropsToBeRemoved.isEmpty()) {
1073                     areSubstitutionNodePropertiesInUse(currentService, subNodePropsToBeRemoved);
1074                 }
1075                 currentService.setDerivedFromGenericVersion(serviceUpdate.getDerivedFromGenericVersion());
1076                 currentService.setDerivedFromGenericType(serviceUpdate.getDerivedFromGenericType());
1077             }
1078
1079             Either<Boolean, ResponseFormat> response = validateAndUpdateCategory(user, currentService, serviceUpdate, hasBeenCertified,
1080                 UPDATE_SERVICE_METADATA);
1081             if (response.isRight()) {
1082                 ResponseFormat errorResponse = response.right().value();
1083                 return Either.right(errorResponse);
1084             }
1085             verifyValuesAreIdentical(serviceUpdate.getCreatorUserId(), currentService.getCreatorUserId(), "creatorUserId");
1086             verifyValuesAreIdentical(serviceUpdate.getCreatorFullName(), currentService.getCreatorFullName(), "creatorFullName");
1087             verifyValuesAreIdentical(serviceUpdate.getLastUpdaterUserId(), currentService.getLastUpdaterUserId(), "lastUpdaterUserId");
1088             verifyValuesAreIdentical(serviceUpdate.getLastUpdaterFullName(), currentService.getLastUpdaterFullName(), "lastUpdaterFullName");
1089             response = validateAndUpdateServiceName(user, currentService, serviceUpdate, hasBeenCertified, null);
1090             if (response.isRight()) {
1091                 return Either.right(response.right().value());
1092             }
1093             verifyValuesAreIdentical(serviceUpdate.getDistributionStatus(), currentService.getDistributionStatus(), "distributionStatus");
1094             if (serviceUpdate.getProjectCode() != null) {
1095                 response = validateAndUpdateProjectCode(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
1096                 if (response.isRight()) {
1097                     return Either.right(response.right().value());
1098                 }
1099             }
1100             response = validateAndUpdateIcon(user, currentService, serviceUpdate, hasBeenCertified, UPDATE_SERVICE_METADATA);
1101             if (response.isRight()) {
1102                 return Either.right(response.right().value());
1103             }
1104             verifyValuesAreIdentical(serviceUpdate.getCreationDate(), currentService.getCreationDate(), "creationDate");
1105             verifyValuesAreIdentical(serviceUpdate.getVersion(), currentService.getVersion(), "version");
1106             response = validateAndUpdateDescription(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
1107             if (response.isRight()) {
1108                 return Either.right(response.right().value());
1109             }
1110             response = validateAndUpdateTags(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
1111             if (response.isRight()) {
1112                 return Either.right(response.right().value());
1113             }
1114             response = validateAndUpdateContactId(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
1115             if (response.isRight()) {
1116                 return Either.right(response.right().value());
1117             }
1118             verifyValuesAreIdentical(serviceUpdate.getLastUpdateDate(), currentService.getLastUpdateDate(), "lastUpdateDate");
1119             verifyValuesAreIdentical(serviceUpdate.getLifecycleState(), currentService.getLifecycleState(), "lifecycleState");
1120             verifyValuesAreIdentical(serviceUpdate.isHighestVersion(), currentService.isHighestVersion(), "isHighestVersion");
1121             verifyValuesAreIdentical(serviceUpdate.getUUID(), currentService.getUUID(), "uuid");
1122             validateAndUpdateServiceType(currentService, serviceUpdate);
1123             validateAndUpdateServiceFunction(currentService, serviceUpdate);
1124             response = validateAndUpdateServiceRole(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
1125             if (response.isRight()) {
1126                 return Either.right(response.right().value());
1127             }
1128             response = validateAndUpdateInstantiationTypeValue(user, currentService, serviceUpdate, UPDATE_SERVICE_METADATA);
1129             if (response.isRight()) {
1130                 return Either.right(response.right().value());
1131             }
1132             verifyValuesAreIdentical(serviceUpdate.getInvariantUUID(), currentService.getInvariantUUID(), "invariantUUID");
1133             validateAndUpdateEcompNaming(currentService, serviceUpdate);
1134             currentService.setEnvironmentContext(serviceUpdate.getEnvironmentContext());
1135             currentService.setCategorySpecificMetadata(serviceUpdate.getCategorySpecificMetadata());
1136             return Either.left(currentService);
1137         } catch (ComponentException exception) {
1138             ResponseFormat responseFormat = componentsUtils.getResponseFormat(exception);
1139             componentsUtils
1140                 .auditComponentAdmin(responseFormat, user, serviceUpdate, AuditingActionEnum.UPDATE_SERVICE_METADATA, ComponentTypeEnum.SERVICE);
1141             return Either.right(responseFormat);
1142         }
1143     }
1144
1145     private void addPropertiesToService(Service currentService, List<PropertyDefinition> subNodePropsToBeAdded) {
1146         ListUtils.emptyIfNull(subNodePropsToBeAdded).forEach(prop -> {
1147             Either<PropertyDefinition, StorageOperationStatus> addPropertyEither =
1148                 toscaOperationFacade.addPropertyToComponent(prop, currentService);
1149             if (addPropertyEither.isRight()) {
1150                 throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
1151             }
1152         });
1153     }
1154
1155     private void addInputsToService(Service currentService, List<PropertyDefinition> subNodePropsToBeAdded) {
1156         ListUtils.emptyIfNull(subNodePropsToBeAdded).forEach(prop -> {
1157             InputDefinition inputDef = new InputDefinition(prop);
1158             Either<InputDefinition, StorageOperationStatus> status =
1159                 toscaOperationFacade.addInputToComponent(prop.getName(), inputDef, currentService);
1160             if (status.isRight()) {
1161                 throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
1162             }
1163         });
1164     }
1165
1166     private void removePropertiesFromService(Service currentService, List<String> subNodePropsToBeRemoved) {
1167         List<PropertyDefinition> props = currentService.getProperties();
1168         List<String> propsUniqueIdsToBeRemoved =
1169             props.stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName())).map(PropertyDefinition::getUniqueId)
1170                 .collect(Collectors.toList());
1171         ListUtils.emptyIfNull(props).stream().filter(prop -> propsUniqueIdsToBeRemoved.contains(prop.getUniqueId())).forEach(prop -> {
1172             StorageOperationStatus status = toscaOperationFacade.deletePropertyOfComponent(currentService, prop.getName());
1173             if (status != StorageOperationStatus.OK) {
1174                 throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
1175             }
1176         });
1177     }
1178
1179     private void removeInputsFromService(Service currentService, List<String> subNodePropsToBeRemoved) {
1180         List<PropertyDefinition> props = currentService.getProperties();
1181         List<InputDefinition> inputs = currentService.getInputs();
1182         List<String> propsUniqueIdsToBeRemoved =
1183             props.stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName())).map(PropertyDefinition::getUniqueId)
1184                 .collect(Collectors.toList());
1185         ListUtils.emptyIfNull(inputs).stream().filter(input -> input.isMappedToComponentProperty() &&
1186             (propsUniqueIdsToBeRemoved.contains(input.getPropertyId()) || subNodePropsToBeRemoved.contains(input.getName()))).forEach(input -> {
1187             StorageOperationStatus status = toscaOperationFacade.deleteInputOfResource(currentService, input.getName());
1188             if (status != StorageOperationStatus.OK) {
1189                 throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
1190             }
1191         });
1192     }
1193
1194     private void areSubstitutionNodePropertiesInUse(Service service, List<String> subNodePropsToBeRemoved) {
1195         Map<String, List<ComponentInstanceProperty>> componentInstancesProps = service.getComponentInstancesProperties();
1196         List<String> propsUniqueIdsToBeRemoved =
1197             ListUtils.emptyIfNull(service.getProperties()).stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName()))
1198                 .map(PropertyDefinition::getUniqueId)
1199                 .collect(Collectors.toList());
1200         List<String> inputsUniqueIdsToBeRemoved = ListUtils.emptyIfNull(service.getInputs()).stream()
1201             .filter(input -> propsUniqueIdsToBeRemoved.contains(input.getPropertyId()) || subNodePropsToBeRemoved.contains(input.getName()))
1202             .map(PropertyDefinition::getUniqueId)
1203             .collect(Collectors.toList());
1204         Map<String, List<String>> inUse = new HashMap<>();
1205         if (componentInstancesProps != null && !componentInstancesProps.isEmpty()) {
1206             componentInstancesProps.forEach((compInstanceId, listOfProps) -> {
1207                 List<String> propsInUse = new ArrayList<>();
1208                 listOfProps.stream()
1209                     .filter(PropertyDataDefinition::isToscaFunction)
1210                     .filter(compProp -> ToscaFunctionType.isGetFunction(compProp.getToscaFunction().getType()))
1211                     .forEach(compProp -> {
1212                         ToscaFunction toscaFunction = compProp.getToscaFunction();
1213                         ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction;
1214                         String propName = toscaGetFunction.getPropertyName();
1215                         String propUniqueId = toscaGetFunction.getPropertyUniqueId();
1216                         if (inputsUniqueIdsToBeRemoved.contains(propUniqueId) || propsUniqueIdsToBeRemoved.contains(propUniqueId) ||
1217                             subNodePropsToBeRemoved.contains(propName)) {
1218                             propsInUse.add(compProp.getName());
1219                         }
1220                     });
1221                 if (!propsInUse.isEmpty()) {
1222                     Optional<ComponentInstance> componentInstance = service.getComponentInstanceById(compInstanceId);
1223                     componentInstance.ifPresent(instance -> inUse.put(instance.getName(), propsInUse));
1224                 }
1225
1226             });
1227         }
1228         if (!inUse.isEmpty()) {
1229             String propsInUse = inUse.entrySet().stream().map(entry -> {
1230                 String properties = entry.getValue().stream().map(Object::toString).collect(Collectors.joining(", "));
1231                 return properties + " on " + entry.getKey();
1232             }).collect(Collectors.joining(", properties "));
1233             throw new ByActionStatusComponentException(ActionStatus.SUBSTITUTION_NODE_TYPE_PROPERTY_IN_USE, propsInUse);
1234         }
1235     }
1236
1237
1238     private boolean isSubstitutionNodeChanged(Service currentService, Service updatedService) {
1239         String currentServiceType = currentService.getDerivedFromGenericType();
1240         String updatedServiceType = updatedService.getDerivedFromGenericType();
1241         String currentServiceVersion = currentService.getDerivedFromGenericVersion();
1242         String updatedServiceVersion = updatedService.getDerivedFromGenericVersion();
1243         return !(StringUtils.equals(currentServiceType, updatedServiceType) && StringUtils.equals(currentServiceVersion, updatedServiceVersion));
1244     }
1245
1246     private List<String> getSubstitutionNodePropertiesToBeRemoved(Service currentService, Service serviceUpdate) {
1247         List<PropertyDefinition> currentProps = ListUtils.emptyIfNull(fetchDerivedFromGenericType(currentService, null).getProperties());
1248         List<PropertyDefinition> updatedProps = ListUtils.emptyIfNull(fetchDerivedFromGenericType(serviceUpdate, null).getProperties());
1249         if (!StringUtils.equals(currentService.getDerivedFromGenericType(), serviceUpdate.getDerivedFromGenericType())) {
1250             return currentProps.stream().map(PropertyDefinition::getName).collect(Collectors.toList());
1251         }
1252
1253         Map<String, PropertyDefinition> currentPropsMap = currentProps.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
1254         Map<String, PropertyDefinition> updatedPropsMap = updatedProps.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
1255
1256         List<String> propNamesToBeRemoved = new ArrayList<>();
1257         for (String currentPropertyName : currentPropsMap.keySet()) {
1258             if (updatedPropsMap.containsKey(currentPropertyName)) {
1259                 if (!haveSameType(currentPropsMap.get(currentPropertyName), updatedPropsMap.get(currentPropertyName))) {
1260                     propNamesToBeRemoved.add(currentPropertyName);
1261                 }
1262             } else {
1263                 propNamesToBeRemoved.add(currentPropertyName);
1264             }
1265         }
1266
1267         return propNamesToBeRemoved;
1268     }
1269
1270     private boolean haveSameType(final PropertyDefinition property1, final PropertyDefinition property2) {
1271         if (property1.getType().equals("list")) {
1272             return property2.getType().equals("list") && property1.getSchema().equals(property2.getSchema());
1273         }
1274         if (property1.getType().equals("map")) {
1275             return property2.getType().equals("map") && property1.getSchema().equals(property2.getSchema());
1276         }
1277         return property1.getType().equals(property2.getType());
1278     }
1279
1280     private List<PropertyDefinition> getSubstitutionNodePropertiesToBeAdded(Service currentService, Service serviceUpdate) {
1281         List<PropertyDefinition> propsInCurrentVersion = ListUtils.emptyIfNull(fetchDerivedFromGenericType(currentService, null).getProperties());
1282         List<PropertyDefinition> propsInUpdatedVersion = ListUtils.emptyIfNull(fetchDerivedFromGenericType(serviceUpdate, null).getProperties());
1283         if (!StringUtils.equals(currentService.getDerivedFromGenericType(), serviceUpdate.getDerivedFromGenericType())) {
1284             return propsInUpdatedVersion;
1285         }
1286
1287         Map<String, PropertyDefinition> mapOfPropsInCurrentVersion = propsInCurrentVersion.stream()
1288             .collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
1289         Map<String, PropertyDefinition> mapOfPropsInUpdatedVersion = propsInUpdatedVersion.stream()
1290             .collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
1291
1292         List<PropertyDefinition> propsToBeAdded = new ArrayList<>();
1293         for (Entry<String, PropertyDefinition> propertyInUpdatedVersion : mapOfPropsInUpdatedVersion.entrySet()) {
1294             if (mapOfPropsInCurrentVersion.containsKey(propertyInUpdatedVersion.getKey())) {
1295                 if (!haveSameType(mapOfPropsInCurrentVersion.get(propertyInUpdatedVersion.getKey()), propertyInUpdatedVersion.getValue())) {
1296                     propsToBeAdded.add(propertyInUpdatedVersion.getValue());
1297                 }
1298             } else {
1299                 propsToBeAdded.add(propertyInUpdatedVersion.getValue());
1300             }
1301         }
1302
1303         return propsToBeAdded;
1304     }
1305
1306
1307     private void verifyValuesAreIdentical(Object updatedValue, Object originalValue, String fieldName) {
1308         if (updatedValue != null && !updatedValue.equals(originalValue)) {
1309             log.info("update service: received request to update {} to {} the field is not updatable ignoring.", fieldName, updatedValue);
1310         }
1311     }
1312
1313     private void validateAndUpdateEcompNaming(Service currentService, Service serviceUpdate) {
1314         Boolean isEcompGeneratedCurr = currentService.isEcompGeneratedNaming();
1315         Boolean isEcompGeneratedUpdate = serviceUpdate.isEcompGeneratedNaming();
1316         if (isEcompGeneratedUpdate != null && !isEcompGeneratedUpdate.equals(isEcompGeneratedCurr)) {
1317             currentService.setEcompGeneratedNaming(isEcompGeneratedUpdate);
1318         }
1319         String namingPolicyUpdate = serviceUpdate.getNamingPolicy();
1320         if (currentService.isEcompGeneratedNaming() != null && currentService.isEcompGeneratedNaming()) {
1321             currentService.setNamingPolicy(namingPolicyUpdate);
1322         } else {
1323             if (!StringUtils.isEmpty(namingPolicyUpdate)) {
1324                 log.warn("NamingPolicy must be empty for EcompGeneratedNaming=false");
1325             }
1326             currentService.setNamingPolicy("");
1327         }
1328     }
1329
1330     private Either<Boolean, ResponseFormat> validateAndUpdateContactId(User user, Service currentService, Service serviceUpdate,
1331                                                                        AuditingActionEnum audatingAction) {
1332         String contactIdUpdated = serviceUpdate.getContactId();
1333         String contactIdCurrent = currentService.getContactId();
1334         if (!contactIdCurrent.equals(contactIdUpdated)) {
1335             componentContactIdValidator.validateAndCorrectField(user, serviceUpdate, audatingAction);
1336             currentService.setContactId(contactIdUpdated.toLowerCase());
1337         }
1338         return Either.left(true);
1339     }
1340
1341     private Either<Boolean, ResponseFormat> validateAndUpdateTags(User user, Service currentService, Service serviceUpdate,
1342                                                                   AuditingActionEnum audatingAction) {
1343         List<String> tagsUpdated = serviceUpdate.getTags();
1344         List<String> tagsCurrent = currentService.getTags();
1345         if (tagsUpdated == null || tagsUpdated.isEmpty()) {
1346             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_TAGS);
1347             componentsUtils.auditComponentAdmin(responseFormat, user, serviceUpdate, audatingAction, ComponentTypeEnum.SERVICE);
1348             return Either.right(responseFormat);
1349         }
1350         if (!(tagsCurrent.containsAll(tagsUpdated) && tagsUpdated.containsAll(tagsCurrent))) {
1351             componentTagsValidator.validateAndCorrectField(user, serviceUpdate, audatingAction);
1352             currentService.setTags(tagsUpdated);
1353         }
1354         return Either.left(true);
1355     }
1356
1357     private Either<Boolean, ResponseFormat> validateAndUpdateDescription(User user, Service currentService, Service serviceUpdate,
1358                                                                          AuditingActionEnum audatingAction) {
1359         String descriptionUpdated = serviceUpdate.getDescription();
1360         String descriptionCurrent = currentService.getDescription();
1361         if (!descriptionCurrent.equals(descriptionUpdated)) {
1362             componentDescriptionValidator.validateAndCorrectField(user, serviceUpdate, audatingAction);
1363             currentService.setDescription(serviceUpdate.getDescription());
1364         }
1365         return Either.left(true);
1366     }
1367
1368     private Either<Boolean, ResponseFormat> validateAndUpdateProjectCode(User user, Service currentService, Service serviceUpdate,
1369                                                                          AuditingActionEnum audatingAction) {
1370         String projectCodeUpdated = serviceUpdate.getProjectCode();
1371         String projectCodeCurrent = currentService.getProjectCode();
1372         if (StringUtils.isEmpty(projectCodeCurrent) || !projectCodeCurrent.equals(projectCodeUpdated)) {
1373             try {
1374                 componentProjectCodeValidator.validateAndCorrectField(user, serviceUpdate, audatingAction);
1375             } catch (ComponentException exp) {
1376                 ResponseFormat errorRespons = exp.getResponseFormat();
1377                 return Either.right(errorRespons);
1378             }
1379             currentService.setProjectCode(projectCodeUpdated);
1380         }
1381         return Either.left(true);
1382     }
1383
1384     private Either<Boolean, ResponseFormat> validateAndUpdateIcon(User user, Service currentService, Service serviceUpdate, boolean hasBeenCertified,
1385                                                                   AuditingActionEnum audatingAction) {
1386         String iconUpdated = serviceUpdate.getIcon();
1387         String iconCurrent = currentService.getIcon();
1388         if (!iconCurrent.equals(iconUpdated)) {
1389             if (!hasBeenCertified) {
1390                 componentIconValidator.validateAndCorrectField(user, serviceUpdate, audatingAction);
1391                 currentService.setIcon(iconUpdated);
1392             } else {
1393                 log.info("icon {} cannot be updated once the service has been certified once.", iconUpdated);
1394                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_ICON_CANNOT_BE_CHANGED);
1395                 return Either.right(errorResponse);
1396             }
1397         }
1398         return Either.left(true);
1399     }
1400
1401     private Either<Boolean, ResponseFormat> validateAndUpdateServiceName(User user, Service currentService, Service serviceUpdate,
1402                                                                          boolean hasBeenCertified, AuditingActionEnum auditingAction) {
1403         String serviceNameUpdated = serviceUpdate.getName();
1404         String serviceNameCurrent = currentService.getName();
1405         if (!serviceNameCurrent.equals(serviceNameUpdated)) {
1406             if (!hasBeenCertified) {
1407                 componentNameValidator.validateAndCorrectField(user, serviceUpdate, auditingAction);
1408                 try {
1409                     componentNameValidator.validateComponentNameUnique(user, serviceUpdate, auditingAction);
1410                 } catch (ComponentException exp) {
1411                     return Either.right(exp.getResponseFormat());
1412                 }
1413                 currentService.setName(serviceNameUpdated);
1414                 currentService.getComponentMetadataDefinition().getMetadataDataDefinition()
1415                     .setNormalizedName(ValidationUtils.normaliseComponentName(serviceNameUpdated));
1416                 currentService.getComponentMetadataDefinition().getMetadataDataDefinition()
1417                     .setSystemName(ValidationUtils.convertToSystemName(serviceNameUpdated));
1418             } else {
1419                 log.info("service name {} cannot be updated once the service has been certified once.", serviceNameUpdated);
1420                 ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_NAME_CANNOT_BE_CHANGED);
1421                 return Either.right(errorResponse);
1422             }
1423         }
1424         return Either.left(true);
1425     }
1426
1427     private void validateAndUpdateServiceType(Service currentService, Service updatedService) {
1428         String updatedServiceType = updatedService.getServiceType();
1429         String currentServiceType = currentService.getServiceType();
1430         if (!currentServiceType.equals(updatedServiceType)) {
1431             serviceTypeValidator.validateAndCorrectField(null, updatedService, null);
1432             currentService.setServiceType(updatedServiceType);
1433         }
1434     }
1435
1436     private void validateAndUpdateServiceFunction(Service currentService, Service updatedService) {
1437         String updatedServiceFunction = updatedService.getServiceFunction();
1438         String currentServiceFunction = currentService.getServiceFunction();
1439         if (!currentServiceFunction.equals(updatedServiceFunction)) {
1440             serviceFunctionValidator.validateAndCorrectField(null, updatedService, null);
1441             currentService.setServiceFunction(updatedService.getServiceFunction());
1442         }
1443     }
1444
1445     private Either<Boolean, ResponseFormat> validateAndUpdateServiceRole(User user, Service currentService, Service updatedService,
1446                                                                          AuditingActionEnum auditingAction) {
1447         String updatedServiceRole = updatedService.getServiceRole();
1448         String currentServiceRole = currentService.getServiceRole();
1449         if (!currentServiceRole.equals(updatedServiceRole)) {
1450             try {
1451                 serviceRoleValidator.validateAndCorrectField(user, updatedService, auditingAction);
1452             } catch (ComponentException exp) {
1453                 ResponseFormat errorResponse = exp.getResponseFormat();
1454                 componentsUtils.auditComponentAdmin(errorResponse, user, updatedService, auditingAction, ComponentTypeEnum.SERVICE);
1455                 return Either.right(errorResponse);
1456             }
1457             currentService.setServiceRole(updatedServiceRole);
1458         }
1459         return Either.left(true);
1460     }
1461
1462     private Either<Boolean, ResponseFormat> validateAndUpdateInstantiationTypeValue(User user, Service currentService, Service updatedService,
1463                                                                                     AuditingActionEnum auditingAction) {
1464         String updatedInstaType = updatedService.getInstantiationType();
1465         String currentInstaType = currentService.getInstantiationType();
1466         if (!currentInstaType.equals(updatedInstaType)) {
1467             try {
1468                 serviceInstantiationTypeValidator.validateAndCorrectField(user, updatedService, auditingAction);
1469             } catch (ComponentException exp) {
1470                 ResponseFormat errorResponse = exp.getResponseFormat();
1471                 componentsUtils.auditComponentAdmin(errorResponse, user, updatedService, auditingAction, ComponentTypeEnum.SERVICE);
1472                 return Either.right(errorResponse);
1473             }
1474             currentService.setInstantiationType(updatedInstaType);
1475         }
1476         return Either.left(true);
1477     }
1478
1479     private Either<Boolean, ResponseFormat> validateAndUpdateCategory(User user, Service currentService, Service serviceUpdate,
1480                                                                       boolean hasBeenCertified, AuditingActionEnum audatingAction) {
1481         try {
1482             List<CategoryDefinition> categoryUpdated = serviceUpdate.getCategories();
1483             List<CategoryDefinition> categoryCurrent = currentService.getCategories();
1484             serviceCategoryValidator.validateAndCorrectField(user, serviceUpdate, audatingAction);
1485             if (!categoryCurrent.get(0).getName().equals(categoryUpdated.get(0).getName())) {
1486                 if (!hasBeenCertified) {
1487                     currentService.setCategories(categoryUpdated);
1488                 } else {
1489                     log.info("category {} cannot be updated once the service has been certified once.", categoryUpdated);
1490                     ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.SERVICE_CATEGORY_CANNOT_BE_CHANGED);
1491                     return Either.right(errorResponse);
1492                 }
1493             }
1494         } catch (ComponentException exp) {
1495             return Either.right(exp.getResponseFormat());
1496         }
1497         return Either.left(true);
1498     }
1499
1500     public Either<ServiceRelations, ResponseFormat> getServiceComponentsRelations(String serviceId, User user) {
1501         Either<Service, ResponseFormat> serviceResponseFormatEither = getService(serviceId, user);
1502         if (serviceResponseFormatEither.isRight()) {
1503             return Either.right(serviceResponseFormatEither.right().value());
1504         }
1505         final ServiceRelations serviceRelations = new ForwardingPathUtils()
1506             .convertServiceToServiceRelations(serviceResponseFormatEither.left().value());
1507         return Either.left(serviceRelations);
1508     }
1509
1510     public void deleteServiceAllVersions(String serviceId, User user) {
1511         validateUserExists(user);
1512         Either<Service, StorageOperationStatus> serviceStatus = toscaOperationFacade.getToscaElement(serviceId);
1513         if (serviceStatus.isRight()) {
1514             log.debug("Failed to get service {}", serviceId);
1515             componentException(serviceStatus.right().value());
1516         }
1517         Service service = serviceStatus.left().value();
1518         if (Boolean.FALSE.equals(service.isArchived())) {
1519             log.debug("The service, {}, requested for delete has not been archived.", serviceId);
1520             throw new ComponentException(ActionStatus.COMPONENT_NOT_ARCHIVED, serviceId);
1521         }
1522         List<String> deletedServiceList = new ArrayList<>();
1523         try {
1524             String model = service.getModel();
1525             final Optional<Model> modelOptional = modelOperation.findModelByName(model);
1526             deletedServiceList = toscaOperationFacade.deleteService(service.getInvariantUUID(), true);
1527             if (log.isDebugEnabled()) {
1528                 deletedServiceList.forEach(deletedS -> log.debug("Component {} was deleted.", deletedS));
1529             }
1530             if (modelOptional.isPresent() && modelOptional.get().getModelType() == ModelTypeEnum.NORMATIVE_EXTENSION) {
1531                 modelOperation.deleteModel(modelOptional.get(), false);
1532             }
1533             toscaOperationFacade.commitAndCheck(service.getUniqueId());
1534             updateCatalog(service, ChangeTypeEnum.DELETE);
1535         } catch (ComponentException exception) {
1536             log.debug("Failed to delete service, {}, in ServiceServlet", serviceId);
1537             janusGraphDao.rollback();
1538             throw exception;
1539         }
1540     }
1541
1542     public ResponseFormat markServiceForDeletion(String serviceId, User user) {
1543         ResponseFormat responseFormat;
1544         validateUserExists(user);
1545         Either<Service, StorageOperationStatus> serviceStatus = toscaOperationFacade.getToscaElement(serviceId);
1546         if (serviceStatus.isRight()) {
1547             log.debug("failed to get service {}", serviceId);
1548             return componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(serviceStatus.right().value()), "");
1549         }
1550         Service service = serviceStatus.left().value();
1551         StorageOperationStatus result = StorageOperationStatus.OK;
1552         try {
1553             lockComponent(service, "Mark service to delete");
1554             result = markComponentToDelete(service);
1555             if (result == StorageOperationStatus.OK) {
1556                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.NO_CONTENT);
1557             } else {
1558                 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(result);
1559                 responseFormat = componentsUtils.getResponseFormatByResource(actionStatus, service.getName());
1560             }
1561             return responseFormat;
1562         } catch (ComponentException e) {
1563             return e.getResponseFormat();
1564         } finally {
1565             if (result == null || result != StorageOperationStatus.OK) {
1566                 log.warn("operation failed. do rollback");
1567                 BeEcompErrorManager.getInstance().logBeSystemError("Delete Service");
1568                 janusGraphDao.rollback();
1569             } else {
1570                 log.debug("operation success. do commit");
1571                 janusGraphDao.commit();
1572             }
1573             graphLockOperation.unlockComponent(serviceId, NodeTypeEnum.Service);
1574         }
1575     }
1576
1577     public ResponseFormat deleteServiceByNameAndVersion(String serviceName, String version, User user) {
1578         ResponseFormat responseFormat;
1579         String ecompErrorContext = "delete service";
1580         validateUserNotEmpty(user, ecompErrorContext);
1581         user = validateUserExists(user);
1582         Either<Service, ResponseFormat> getResult = getServiceByNameAndVersion(serviceName, version, user.getUserId());
1583         if (getResult.isRight()) {
1584             return getResult.right().value();
1585         }
1586         Service service = getResult.left().value();
1587         StorageOperationStatus result = StorageOperationStatus.OK;
1588         try {
1589             lockComponent(service, "Mark service to delete");
1590             result = markComponentToDelete(service);
1591             if (result == StorageOperationStatus.OK) {
1592                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.NO_CONTENT);
1593             } else {
1594                 ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(result);
1595                 responseFormat = componentsUtils.getResponseFormatByResource(actionStatus, service.getName());
1596             }
1597             return responseFormat;
1598         } catch (ComponentException e) {
1599             result = StorageOperationStatus.GENERAL_ERROR;
1600             return componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
1601         } finally {
1602             if (result == null || result != StorageOperationStatus.OK) {
1603                 log.warn("operation failed. do rollback");
1604                 BeEcompErrorManager.getInstance().logBeSystemError("Delete Service");
1605                 janusGraphDao.rollback();
1606             } else {
1607                 log.debug("operation success. do commit");
1608                 janusGraphDao.commit();
1609             }
1610             graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service);
1611         }
1612     }
1613
1614     public Either<Service, ResponseFormat> getService(String serviceId, User user) {
1615         String ecompErrorContext = "Get service";
1616         validateUserNotEmpty(user, ecompErrorContext);
1617         validateUserExists(user);
1618         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(serviceId);
1619         if (storageStatus.isRight()) {
1620             log.debug("failed to get service by id {}", serviceId);
1621             return Either.right(componentsUtils
1622                 .getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), serviceId));
1623         }
1624         if (!(storageStatus.left().value() instanceof Service)) {
1625             return Either
1626                 .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND), serviceId));
1627         }
1628         Service service = storageStatus.left().value();
1629         return Either.left(service);
1630     }
1631
1632     public Either<Service, ResponseFormat> getServiceByNameAndVersion(String serviceName, String serviceVersion, String userId) {
1633         validateUserExists(userId);
1634         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade
1635             .getComponentByNameAndVersion(ComponentTypeEnum.SERVICE, serviceName, serviceVersion);
1636         if (storageStatus.isRight()) {
1637             log.debug("failed to get service by name {} and version {}", serviceName, serviceVersion);
1638             return Either.right(componentsUtils
1639                 .getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE),
1640                     serviceName));
1641         }
1642         Service service = storageStatus.left().value();
1643         return Either.left(service);
1644     }
1645
1646     @SuppressWarnings("unchecked")
1647     private void createMandatoryArtifactsData(Service service, User user) {
1648         // create mandatory artifacts
1649
1650         // TODO it must be removed after that artifact uniqueId creation will be
1651
1652         // moved to ArtifactOperation
1653         String serviceUniqueId = service.getUniqueId();
1654         Map<String, ArtifactDefinition> artifactMap = service.getArtifacts();
1655         if (artifactMap == null) {
1656             artifactMap = new HashMap<>();
1657         }
1658         Map<String, Object> informationalServiceArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration()
1659             .getInformationalServiceArtifacts();
1660         List<String> exludeServiceCategory = ConfigurationManager.getConfigurationManager().getConfiguration().getExcludeServiceCategory();
1661         String category = service.getCategories().get(0).getName();
1662         boolean isCreateArtifact = true;
1663         if (category != null && exludeServiceCategory != null && !exludeServiceCategory.isEmpty()) {
1664             for (String exlude : exludeServiceCategory) {
1665                 if (exlude.equalsIgnoreCase(category)) {
1666                     isCreateArtifact = false;
1667                     break;
1668                 }
1669             }
1670         }
1671         if (informationalServiceArtifacts != null && isCreateArtifact) {
1672             Set<String> keys = informationalServiceArtifacts.keySet();
1673             for (String informationalServiceArtifactName : keys) {
1674                 Map<String, Object> artifactInfoMap = (Map<String, Object>) informationalServiceArtifacts.get(informationalServiceArtifactName);
1675                 ArtifactDefinition artifactDefinition = createArtifactDefinition(serviceUniqueId, informationalServiceArtifactName, artifactInfoMap,
1676                     user, false);
1677                 artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition);
1678             }
1679             service.setArtifacts(artifactMap);
1680         }
1681     }
1682
1683     private ArtifactDefinition createArtifactDefinition(String serviceId, String logicalName, Map<String, Object> artifactInfoMap, User user,
1684                                                         Boolean isServiceApi) {
1685         ArtifactDefinition artifactInfo = artifactsBusinessLogic
1686             .createArtifactPlaceHolderInfo(serviceId, logicalName, artifactInfoMap, user, ArtifactGroupTypeEnum.INFORMATIONAL);
1687         if (Boolean.TRUE.equals(isServiceApi)) {
1688             artifactInfo.setMandatory(false);
1689             artifactInfo.setServiceApi(true);
1690         }
1691         return artifactInfo;
1692     }
1693
1694     private String getEnvNameFromConfiguration() {
1695         String configuredEnvName = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration().getEnvironments().get(0);
1696         log.trace("Update environment name to be {}", configuredEnvName);
1697         return configuredEnvName;
1698     }
1699
1700     public Either<String, ResponseFormat> activateServiceOnTenantEnvironment(String serviceId, String envId, User modifier,
1701                                                                              ServiceDistributionReqInfo data) {
1702         Either<ActivationRequestInformation, ResponseFormat> activationRequestInformationEither = serviceDistributionValidation
1703             .validateActivateServiceRequest(serviceId, envId, modifier, data);
1704         if (activationRequestInformationEither.isRight()) {
1705             return Either.right(activationRequestInformationEither.right().value());
1706         }
1707         ActivationRequestInformation activationRequestInformation = activationRequestInformationEither.left().value();
1708         String did = ThreadLocalsHolder.getUuid();
1709         Service service = activationRequestInformation.getServiceToActivate();
1710         return buildAndSendServiceNotification(service, envId, did, activationRequestInformation.getWorkloadContext(), modifier);
1711     }
1712
1713     private Either<String, ResponseFormat> buildAndSendServiceNotification(Service service, String envId, String did, String workloadContext,
1714                                                                            User modifier) {
1715         String envName = getEnvNameFromConfiguration();
1716         INotificationData notificationData = distributionEngine.buildServiceForDistribution(service, did, workloadContext);
1717         ActionStatus notifyServiceResponse = distributionEngine.notifyService(did, service, notificationData, envId, envName, modifier);
1718         if (notifyServiceResponse == ActionStatus.OK) {
1719             return Either.left(did);
1720         } else {
1721             BeEcompErrorManager.getInstance().logBeSystemError("Activate Distribution - send notification");
1722             log.debug("distributionEngine.notifyService response is: {}", notifyServiceResponse);
1723             ResponseFormat error = componentsUtils.getResponseFormat(ActionStatus.INVALID_RESPONSE_FROM_PROXY);
1724             return Either.right(error);
1725         }
1726     }
1727
1728     public Either<Service, ResponseFormat> activateDistribution(String serviceId, String envName, User modifier, HttpServletRequest request) {
1729         User user = validateUserExists(modifier.getUserId());
1730         validateUserRole(user, Collections.singletonList(Role.DESIGNER));
1731         Either<Service, ResponseFormat> result;
1732         ResponseFormat response;
1733         Service updatedService;
1734         String did = ThreadLocalsHolder.getUuid();
1735         // DE194021
1736         String configuredEnvName = ConfigurationManager.getConfigurationManager().getDistributionEngineConfiguration().getEnvironments().get(0);
1737         if (configuredEnvName != null && !configuredEnvName.equals(envName)) {
1738             log.trace("Update environment name to be {} instead of {}", configuredEnvName, envName);
1739             envName = configuredEnvName;
1740         }
1741         if (!kafkaHandler.isKafkaActive()) {
1742             // DE194021
1743             ServletContext servletContext = request.getSession().getServletContext();
1744             boolean isDistributionEngineUp = getHealthCheckBL(servletContext).isDistributionEngineUp(); // DE
1745             if (!isDistributionEngineUp) {
1746                 BeEcompErrorManager.getInstance().logBeSystemError("Distribution Engine is DOWN");
1747                 log.debug("Distribution Engine is DOWN");
1748                 response = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
1749                 return Either.right(response);
1750             }
1751         }
1752         Either<Service, StorageOperationStatus> serviceRes = toscaOperationFacade.getToscaElement(serviceId);
1753         if (serviceRes.isRight()) {
1754             log.debug("failed retrieving service");
1755             response = componentsUtils
1756                 .getResponseFormat(componentsUtils.convertFromStorageResponse(serviceRes.right().value(), ComponentTypeEnum.SERVICE), serviceId);
1757             componentsUtils.auditComponent(response, user, null, AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REQUEST,
1758                 new ResourceCommonInfo(ComponentTypeEnum.SERVICE.getValue()), ResourceVersionInfo.newBuilder().build(), did);
1759             return Either.right(response);
1760         }
1761         Service service = serviceRes.left().value();
1762         if (Boolean.TRUE.equals(service.isArchived())) {
1763             log.info("Component is archived. Component id: {}", serviceId);
1764             return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, service.getName()));
1765         }
1766         if (service.getLifecycleState() != LifecycleStateEnum.CERTIFIED) {
1767             log.info("service {} is  not available for distribution. Should be in certified state", service.getUniqueId());
1768             ResponseFormat responseFormat = componentsUtils
1769                 .getResponseFormat(ActionStatus.SERVICE_NOT_AVAILABLE_FOR_DISTRIBUTION, service.getVersion(), service.getName());
1770             return Either.right(responseFormat);
1771         }
1772         String dcurrStatus = service.getDistributionStatus().name();
1773         String updatedStatus = dcurrStatus;
1774         StorageOperationStatus readyForDistribution = distributionEngine.isReadyForDistribution(envName);
1775         if (readyForDistribution == StorageOperationStatus.OK) {
1776             INotificationData notificationData = distributionEngine.buildServiceForDistribution(service, did, null);
1777             ActionStatus notifyServiceResponse = distributionEngine.notifyService(did, service, notificationData, envName, user);
1778             if (notifyServiceResponse == ActionStatus.OK) {
1779                 Either<Service, ResponseFormat> updateStateRes = updateDistributionStatusForActivation(service, user,
1780                     DistributionStatusEnum.DISTRIBUTED);
1781                 if (updateStateRes.isLeft() && updateStateRes.left().value() != null) {
1782                     updatedService = updateStateRes.left().value();
1783                     updatedStatus = updatedService.getDistributionStatus().name();
1784                 } else {
1785                     // The response is not relevant
1786                     updatedService = service;
1787                 }
1788                 ASDCKpiApi.countActivatedDistribution();
1789                 response = componentsUtils.getResponseFormat(ActionStatus.OK);
1790                 result = Either.left(updatedService);
1791             } else {
1792                 BeEcompErrorManager.getInstance().logBeSystemError("Activate Distribution - send notification");
1793                 log.debug("distributionEngine.notifyService response is: {}", notifyServiceResponse);
1794                 response = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
1795                 result = Either.right(response);
1796             }
1797         } else {
1798             response = componentsUtils
1799                 .getResponseFormatByDE(componentsUtils.convertFromStorageResponse(readyForDistribution, ComponentTypeEnum.SERVICE), envName);
1800             result = Either.right(response);
1801         }
1802         componentsUtils.auditComponent(response, user, service, AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REQUEST,
1803             new ResourceCommonInfo(service.getName(), ComponentTypeEnum.SERVICE.getValue()),
1804             ResourceVersionInfo.newBuilder().distributionStatus(dcurrStatus).build(),
1805             ResourceVersionInfo.newBuilder().distributionStatus(updatedStatus).build(), null, null, did);
1806         return result;
1807     }
1808
1809     // convert to private after deletion of temp url
1810     public Either<Service, ResponseFormat> updateDistributionStatusForActivation(Service service, User user, DistributionStatusEnum state) {
1811         validateUserExists(user.getUserId());
1812         String serviceId = service.getUniqueId();
1813         lockComponent(serviceId, service, "updateDistributionStatusForActivation");
1814         try {
1815             Either<Service, StorageOperationStatus> result = toscaOperationFacade.updateDistributionStatus(service, user, state);
1816             if (result.isRight()) {
1817                 janusGraphDao.rollback();
1818                 BeEcompErrorManager.getInstance().logBeSystemError("updateDistributionStatusForActivation");
1819                 log.debug("service {}  change distribution status failed", serviceId);
1820                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1821             }
1822             janusGraphDao.commit();
1823             updateCatalog(service, ChangeTypeEnum.LIFECYCLE);
1824             return Either.left(result.left().value());
1825         } finally {
1826             graphLockOperation.unlockComponent(serviceId, NodeTypeEnum.Service);
1827         }
1828     }
1829
1830     public Either<Service, ResponseFormat> markDistributionAsDeployed(String serviceId, String did, User user) {
1831         validateUserExists(user.getUserId());
1832         log.debug("mark distribution deployed");
1833         AuditingActionEnum auditAction = AuditingActionEnum.DISTRIBUTION_DEPLOY;
1834         Either<Service, StorageOperationStatus> getServiceResponse = toscaOperationFacade.getToscaElement(serviceId);
1835         if (getServiceResponse.isRight()) {
1836             BeEcompErrorManager.getInstance()
1837                 .logBeComponentMissingError("markDistributionAsDeployed", ComponentTypeEnum.SERVICE.getValue(), serviceId);
1838             log.debug("service {} not found", serviceId);
1839             ResponseFormat responseFormat = auditDeployError(did, user, auditAction, null,
1840                 componentsUtils.convertFromStorageResponse(getServiceResponse.right().value(), ComponentTypeEnum.SERVICE), "");
1841             return Either.right(responseFormat);
1842         }
1843         Service service = getServiceResponse.left().value();
1844         user = validateRoleForDeploy(did, user, auditAction, service);
1845         return checkDistributionAndDeploy(did, user, auditAction, service);
1846     }
1847
1848     public Either<Service, ResponseFormat> generateVfModuleArtifacts(Service service, User modifier, boolean shouldLock, boolean inTransaction) {
1849         Function<ComponentInstance, List<ArtifactGenerator<ArtifactDefinition>>> artifactTaskGeneratorCreator = ri ->
1850             // Only one VF Module Artifact per instance - add it to a list of one
1851             buildArtifactGenList(service, modifier, shouldLock, inTransaction, ri);
1852         return generateDeploymentArtifacts(service, artifactTaskGeneratorCreator);
1853     }
1854
1855     private List<ArtifactGenerator<ArtifactDefinition>> buildArtifactGenList(Service service, User modifier, boolean shouldLock,
1856                                                                              boolean inTransaction, ComponentInstance ri) {
1857         List<ArtifactGenerator<ArtifactDefinition>> asList = new ArrayList<>();
1858         if (ri.getOriginType() == OriginTypeEnum.VF) {
1859             asList = Arrays.asList(new VfModuleArtifactGenerator(modifier, ri, service, shouldLock, inTransaction));
1860         }
1861         return asList;
1862     }
1863
1864     public Either<Service, ResponseFormat> generateHeatEnvArtifacts(Service service, User modifier, boolean shouldLock, boolean inTransaction) {
1865         Function<ComponentInstance, List<ArtifactGenerator<ArtifactDefinition>>> artifactTaskGeneratorCreator = resourceInstance ->
1866             // Get All Deployment Artifacts
1867             service.getComponentInstances().stream().filter(ri -> ri != null && ri == resourceInstance)
1868                 .filter(ri -> ri.getDeploymentArtifacts() != null).flatMap(ri -> ri.getDeploymentArtifacts().values().stream()).
1869                 // Filter in Only Heat Env
1870                     filter(depArtifact -> ArtifactTypeEnum.HEAT_ENV.getType().equals(depArtifact.getArtifactType())).
1871                 // Create ArtifactGenerator from those Artifacts
1872                     map(
1873                     depArtifact -> new HeatEnvArtifactGenerator(depArtifact, service, resourceInstance.getName(), modifier, shouldLock, inTransaction,
1874                         resourceInstance.getUniqueId())).collect(Collectors.toList());
1875         return generateDeploymentArtifacts(service, artifactTaskGeneratorCreator);
1876     }
1877
1878     private <CallVal> Either<Service, ResponseFormat> generateDeploymentArtifacts(Service service,
1879                                                                                   Function<ComponentInstance, List<ArtifactGenerator<CallVal>>> artifactTaskGeneratorCreator) {
1880         // Get Flat List of (Callable) ArtifactGenerator for all the RI in the
1881
1882         // service
1883         if (service.getComponentInstances() != null) {
1884             List<ArtifactGenerator<CallVal>> artifactGenList = service.getComponentInstances().stream()
1885                 .flatMap(ri -> artifactTaskGeneratorCreator.apply(ri).stream()).collect(Collectors.toList());
1886             if (artifactGenList != null && !artifactGenList.isEmpty()) {
1887                 Either<Service, ResponseFormat> callRes = checkDeploymentArtifact(artifactGenList);
1888                 if (callRes != null) {
1889                     return callRes;
1890                 }
1891             }
1892         }
1893         Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaFullElement(service.getUniqueId());
1894         if (storageStatus.isRight()) {
1895             return Either.right(componentsUtils
1896                 .getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), ""));
1897         }
1898         Service currentService = storageStatus.left().value();
1899         return Either.left(currentService);
1900     }
1901
1902     private <CallVal> Either<Service, ResponseFormat> checkDeploymentArtifact(List<ArtifactGenerator<CallVal>> artifactGenList) {
1903         for (ArtifactGenerator<CallVal> entry : artifactGenList) {
1904             Either<CallVal, ResponseFormat> callRes;
1905             try {
1906                 callRes = entry.call();
1907                 if (callRes.isRight()) {
1908                     log.debug("Failed to generate artifact error : {}", callRes.right().value());
1909                     return Either.right(callRes.right().value());
1910                 }
1911             } catch (Exception e) {
1912                 log.debug("Failed to generate artifact exception : {}", e);
1913                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
1914             }
1915         }
1916         return null;
1917     }
1918
1919     private synchronized Either<Service, ResponseFormat> checkDistributionAndDeploy(String distributionId, User user, AuditingActionEnum auditAction,
1920                                                                                     Service service) {
1921         boolean isDeployed = isDistributionDeployed(distributionId);
1922         if (isDeployed) {
1923             return Either.left(service);
1924         }
1925         Either<Boolean, ResponseFormat> distributionSuccess = checkDistributionSuccess(distributionId, user, auditAction, service);
1926         if (distributionSuccess.isRight()) {
1927             return Either.right(distributionSuccess.right().value());
1928         }
1929         log.debug("mark distribution {} as deployed - success", distributionId);
1930         componentsUtils
1931             .auditServiceDistributionDeployed(service.getName(), service.getVersion(), service.getUUID(), distributionId, STATUS_DEPLOYED, "OK",
1932                 user);
1933         return Either.left(service);
1934     }
1935
1936     private boolean isDistributionDeployed(String distributionId) {
1937         Either<List<DistributionDeployEvent>, ActionStatus> alreadyDeployed = auditCassandraDao
1938             .getDistributionDeployByStatus(distributionId, AuditingActionEnum.DISTRIBUTION_DEPLOY.getName(), STATUS_DEPLOYED);
1939         boolean isDeployed = false;
1940         if (alreadyDeployed.isLeft() && !alreadyDeployed.left().value().isEmpty()) {
1941             // already deployed
1942             log.debug("distribution {} is already deployed", distributionId);
1943             isDeployed = true;
1944         }
1945         return isDeployed;
1946     }
1947
1948     protected Either<Boolean, ResponseFormat> checkDistributionSuccess(String did, User user, AuditingActionEnum auditAction, Service service) {
1949         log.trace("checkDistributionSuccess");
1950         // get all "DRequest" records for this distribution
1951         Either<List<ResourceAdminEvent>, ActionStatus> distRequestsResponse = auditCassandraDao
1952             .getDistributionRequest(did, AuditingActionEnum.DISTRIBUTION_STATE_CHANGE_REQUEST.getName());
1953         if (distRequestsResponse.isRight()) {
1954             ResponseFormat error = auditDeployError(did, user, auditAction, service, distRequestsResponse.right().value());
1955             return Either.right(error);
1956         }
1957         List<ResourceAdminEvent> distributionRequests = distRequestsResponse.left().value();
1958         if (distributionRequests.isEmpty()) {
1959             BeEcompErrorManager.getInstance().logBeDistributionMissingError("markDistributionAsDeployed", did);
1960             log.info("distribution {} is not found", did);
1961             ResponseFormat error = auditDeployError(did, user, auditAction, service, ActionStatus.DISTRIBUTION_REQUESTED_NOT_FOUND);
1962             return Either.right(error);
1963         }
1964         boolean isRequestSucceeded = false;
1965         for (ResourceAdminEvent event : distributionRequests) {
1966             String eventStatus = event.getStatus();
1967             if (eventStatus != null && eventStatus.equals(STATUS_SUCCESS_200)) {
1968                 isRequestSucceeded = true;
1969                 break;
1970             }
1971         }
1972         // get all "DNotify" records for this distribution
1973         Either<List<DistributionNotificationEvent>, ActionStatus> distNotificationsResponse = auditCassandraDao
1974             .getDistributionNotify(did, AuditingActionEnum.DISTRIBUTION_NOTIFY.getName());
1975         if (distNotificationsResponse.isRight()) {
1976             ResponseFormat error = auditDeployError(did, user, auditAction, service, distNotificationsResponse.right().value());
1977             return Either.right(error);
1978         }
1979         List<DistributionNotificationEvent> distributionNotifications = distNotificationsResponse.left().value();
1980         boolean isNotificationsSucceeded = false;
1981         for (DistributionNotificationEvent event : distributionNotifications) {
1982             String eventStatus = event.getStatus();
1983             if (eventStatus != null && eventStatus.equals(STATUS_SUCCESS_200)) {
1984                 isNotificationsSucceeded = true;
1985                 break;
1986             }
1987         }
1988         // if request failed OR there are notifications that failed
1989         if (!(isRequestSucceeded && isNotificationsSucceeded)) {
1990             log.info("distribution {} has failed", did);
1991             ResponseFormat error = componentsUtils.getResponseFormat(ActionStatus.DISTRIBUTION_REQUESTED_FAILED, did);
1992             auditDeployError(did, user, auditAction, service, ActionStatus.DISTRIBUTION_REQUESTED_FAILED, did);
1993             return Either.right(error);
1994         }
1995         return Either.left(true);
1996     }
1997
1998     private ResponseFormat auditDeployError(String did, User user, AuditingActionEnum auditAction, Service service, ActionStatus status,
1999                                             String... params) {
2000         ResponseFormat error = componentsUtils.getResponseFormat(status, params);
2001         String message = "";
2002         if (error.getMessageId() != null) {
2003             message = error.getMessageId() + ": ";
2004         }
2005         message += error.getFormattedMessage();
2006         if (service != null) {
2007             componentsUtils
2008                 .auditServiceDistributionDeployed(service.getName(), service.getVersion(), service.getUUID(), did, error.getStatus().toString(),
2009                     message, user);
2010         } else {
2011             componentsUtils.auditServiceDistributionDeployed("", "", "", did, error.getStatus().toString(), message, user);
2012         }
2013         return error;
2014     }
2015
2016     private User validateRoleForDeploy(String did, User user, AuditingActionEnum auditAction, Service service) {
2017         user = userAdmin.getUser(user.getUserId());
2018         log.debug("validate user role");
2019         List<Role> roles = new ArrayList<>();
2020         roles.add(Role.ADMIN);
2021         roles.add(Role.DESIGNER);
2022         try {
2023             validateUserRole(user, service, roles, auditAction, null);
2024         } catch (ByActionStatusComponentException e) {
2025             log.info("role {} is not allowed to perform this action", user.getRole());
2026             auditDeployError(did, user, auditAction, service, e.getActionStatus());
2027             throw e;
2028         }
2029         return user;
2030     }
2031
2032     @Override
2033     public void setDeploymentArtifactsPlaceHolder(Component component, User user) {
2034         if (component instanceof Service) {
2035             Service service = (Service) component;
2036             Map<String, ArtifactDefinition> artifactMap = service.getDeploymentArtifacts();
2037             if (artifactMap == null) {
2038                 artifactMap = new HashMap<>();
2039             }
2040             service.setDeploymentArtifacts(artifactMap);
2041         } else if (component instanceof Resource) {
2042             Resource resource = (Resource) component;
2043             Map<String, ArtifactDefinition> artifactMap = resource.getDeploymentArtifacts();
2044             if (artifactMap == null) {
2045                 artifactMap = new HashMap<>();
2046             }
2047             Map<String, Object> deploymentResourceArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration()
2048                 .getDeploymentResourceArtifacts();
2049             if (deploymentResourceArtifacts != null) {
2050                 Map<String, ArtifactDefinition> finalArtifactMap = artifactMap;
2051                 deploymentResourceArtifacts.forEach((k, v) -> processDeploymentResourceArtifacts(user, resource, finalArtifactMap, k, v));
2052             }
2053             resource.setDeploymentArtifacts(artifactMap);
2054         }
2055     }
2056
2057     private void processDeploymentResourceArtifacts(User user, Resource resource, Map<String, ArtifactDefinition> artifactMap, String k, Object v) {
2058         Map<String, Object> artifactDetails = (Map<String, Object>) v;
2059         Object object = artifactDetails.get(PLACE_HOLDER_RESOURCE_TYPES);
2060         if (object != null) {
2061             List<String> artifactTypes = (List<String>) object;
2062             if (!artifactTypes.contains(resource.getResourceType().name())) {
2063                 return;
2064             }
2065         } else {
2066             log.info("resource types for artifact placeholder {} were not defined. default is all resources", k);
2067         }
2068         if (artifactsBusinessLogic != null) {
2069             ArtifactDefinition artifactDefinition = artifactsBusinessLogic
2070                 .createArtifactPlaceHolderInfo(resource.getUniqueId(), k, (Map<String, Object>) v, user, ArtifactGroupTypeEnum.DEPLOYMENT);
2071             if (artifactDefinition != null && !artifactMap.containsKey(artifactDefinition.getArtifactLabel())) {
2072                 artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition);
2073             }
2074         }
2075     }
2076
2077     @Override
2078     public Either<List<String>, ResponseFormat> deleteMarkedComponents() {
2079         return deleteMarkedComponents(ComponentTypeEnum.SERVICE);
2080     }
2081
2082     private HealthCheckBusinessLogic getHealthCheckBL(ServletContext context) {
2083         WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context
2084             .getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
2085         WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
2086         return webApplicationContext.getBean(HealthCheckBusinessLogic.class);
2087     }
2088
2089     @Override
2090     public ComponentInstanceBusinessLogic getComponentInstanceBL() {
2091         return componentInstanceBusinessLogic;
2092     }
2093
2094     @Override
2095     public Either<List<ComponentInstance>, ResponseFormat> getComponentInstancesFilteredByPropertiesAndInputs(String componentId, String userId) {
2096         validateUserExists(userId);
2097         Either<Component, StorageOperationStatus> getComponentRes = toscaOperationFacade.getToscaElement(componentId, JsonParseFlagEnum.ParseAll);
2098         if (getComponentRes.isRight()) {
2099             ResponseFormat responseFormat = componentsUtils
2100                 .getResponseFormat(componentsUtils.convertFromStorageResponse(getComponentRes.right().value()));
2101             return Either.right(responseFormat);
2102         }
2103         List<ComponentInstance> componentInstances = getComponentRes.left().value().getComponentInstances();
2104         return Either.left(componentInstances);
2105     }
2106
2107     @Autowired
2108     public void setForwardingPathOperation(ForwardingPathOperation forwardingPathOperation) {
2109         this.forwardingPathOperation = forwardingPathOperation;
2110     }
2111
2112     /**
2113      * updates group instance with new property values in case of successful update of group instance related component instance will be updated with
2114      * new modification time and related service will be updated with new last update date
2115      */
2116     public Either<List<GroupInstanceProperty>, ResponseFormat> updateGroupInstancePropertyValues(User modifier, String serviceId,
2117                                                                                                  String componentInstanceId, String groupInstanceId,
2118                                                                                                  List<GroupInstanceProperty> newProperties) {
2119         Either<List<GroupInstanceProperty>, ResponseFormat> actionResult = null;
2120         Either<ImmutablePair<Component, User>, ResponseFormat> validateUserAndComponentRes;
2121         Component component = null;
2122         Either<Boolean, ResponseFormat> lockResult = null;
2123         log.debug("Going to update group instance {} of service {} with new property values. ", groupInstanceId, serviceId);
2124         try {
2125             validateUserAndComponentRes = validateUserAndComponent(serviceId, modifier);
2126             if (validateUserAndComponentRes.isRight()) {
2127                 log.debug("Cannot update group instance {} of service {} with new property values. Validation failed.  ", groupInstanceId, serviceId);
2128                 actionResult = Either.right(validateUserAndComponentRes.right().value());
2129             }
2130             if (actionResult == null) {
2131                 component = validateUserAndComponentRes.left().value().getKey();
2132                 lockResult = lockComponentByName(component.getSystemName(), component, "Update Group Instance on Service");
2133                 if (lockResult.isRight()) {
2134                     log.debug(FAILED_TO_LOCK_SERVICE_RESPONSE_IS, component.getName(), lockResult.right().value().getFormattedMessage());
2135                     actionResult = Either.right(lockResult.right().value());
2136                 } else {
2137                     log.debug(THE_SERVICE_WITH_SYSTEM_NAME_LOCKED, component.getSystemName());
2138                 }
2139             }
2140             if (actionResult == null) {
2141                 actionResult = validateAndUpdateGroupInstancePropertyValuesAndContainingParents(component, componentInstanceId, groupInstanceId,
2142                     newProperties);
2143                 if (actionResult.isRight()) {
2144                     log.debug("Failed to validate and update group instance {} property values and containing parents. The message is {}. ",
2145                         groupInstanceId, actionResult.right().value().getFormattedMessage());
2146                 }
2147             }
2148         } catch (Exception e) {
2149             log.error("Exception occured during update Group Instance property values: {}", e.getMessage(), e);
2150             actionResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
2151         } finally {
2152             if (lockResult != null && lockResult.isLeft() && Boolean.TRUE.equals(lockResult.left().value())) {
2153                 graphLockOperation.unlockComponentByName(component.getSystemName(), component.getUniqueId(), NodeTypeEnum.Service);
2154             }
2155         }
2156         return actionResult;
2157     }
2158
2159     private Either<List<GroupInstanceProperty>, ResponseFormat> validateAndUpdateGroupInstancePropertyValuesAndContainingParents(Component component,
2160                                                                                                                                  String componentInstanceId,
2161                                                                                                                                  String groupInstanceId,
2162                                                                                                                                  List<GroupInstanceProperty> newProperties) {
2163         Either<List<GroupInstanceProperty>, ResponseFormat> actionResult = null;
2164         Either<ImmutablePair<ComponentInstance, GroupInstance>, ResponseFormat> findGroupInstanceRes;
2165         Either<ImmutablePair<ComponentMetadataData, ComponentInstanceData>, ResponseFormat> updateParentsModificationTimeRes;
2166         ComponentInstance relatedComponentInstance = null;
2167         GroupInstance oldGroupInstance = null;
2168         Either<GroupInstance, ResponseFormat> updateGroupInstanceResult = null;
2169         GroupInstance updatedGroupInstance = null;
2170         boolean inTransaction = true;
2171         findGroupInstanceRes = findGroupInstanceOnRelatedComponentInstance(component, componentInstanceId, groupInstanceId);
2172         if (findGroupInstanceRes.isRight()) {
2173             log.debug("#validateAndUpdateGroupInstancePropertyValuesAndContainingParents - Group instance {} not found. ", groupInstanceId);
2174             actionResult = Either.right(findGroupInstanceRes.right().value());
2175         }
2176         if (actionResult == null) {
2177             oldGroupInstance = findGroupInstanceRes.left().value().getValue();
2178             relatedComponentInstance = findGroupInstanceRes.left().value().getKey();
2179             updateGroupInstanceResult = groupBusinessLogic
2180                 .validateAndUpdateGroupInstancePropertyValues(component.getUniqueId(), componentInstanceId, oldGroupInstance, newProperties);
2181             if (updateGroupInstanceResult.isRight()) {
2182                 log.debug("#validateAndUpdateGroupInstancePropertyValuesAndContainingParents - Failed to update group instance {} property values. ",
2183                     oldGroupInstance.getName());
2184                 actionResult = Either.right(updateGroupInstanceResult.right().value());
2185             }
2186         }
2187         if (actionResult == null) {
2188             updatedGroupInstance = updateGroupInstanceResult.left().value();
2189             if (!oldGroupInstance.getModificationTime().equals(updatedGroupInstance.getModificationTime())) {
2190                 updateParentsModificationTimeRes = updateParentsModificationTimeAndCustomizationUuid(component, relatedComponentInstance,
2191                     updatedGroupInstance, inTransaction);
2192                 if (updateParentsModificationTimeRes.isRight()) {
2193                     log.debug(
2194                         "#validateAndUpdateGroupInstancePropertyValuesAndContainingParents - Failed to update modification time for group instance {}. ",
2195                         oldGroupInstance.getName());
2196                     actionResult = Either.right(updateParentsModificationTimeRes.right().value());
2197                 }
2198             }
2199         }
2200         if (actionResult == null) {
2201             actionResult = Either.left(updatedGroupInstance.convertToGroupInstancesProperties());
2202         }
2203         return actionResult;
2204     }
2205
2206     private Either<ImmutablePair<ComponentMetadataData, ComponentInstanceData>, ResponseFormat> updateParentsModificationTimeAndCustomizationUuid(
2207         Component component, ComponentInstance relatedComponentInstance, GroupInstance updatedGroupInstance, boolean inTranscation) {
2208         Either<ImmutablePair<ComponentMetadataData, ComponentInstanceData>, ResponseFormat> actionResult;
2209         Either<ComponentMetadataData, StorageOperationStatus> serviceMetadataUpdateResult;
2210         Either<ComponentInstanceData, ResponseFormat> updateComponentInstanceRes = componentInstanceBusinessLogic
2211             .updateComponentInstanceModificationTimeAndCustomizationUuid(relatedComponentInstance, NodeTypeEnum.ResourceInstance,
2212                 updatedGroupInstance.getModificationTime(), inTranscation);
2213         if (updateComponentInstanceRes.isRight()) {
2214             log.debug("Failed to update component instance {} after update of group instance {}. ", relatedComponentInstance.getName(),
2215                 updatedGroupInstance.getName());
2216             actionResult = Either.right(updateComponentInstanceRes.right().value());
2217         } else {
2218             serviceMetadataUpdateResult = toscaOperationFacade.updateComponentLastUpdateDateOnGraph(component);
2219             if (serviceMetadataUpdateResult.isRight()) {
2220                 log.debug("Failed to update service {} after update of component instance {} with new property values of group instance {}. ",
2221                     component.getName(), relatedComponentInstance.getName(), updatedGroupInstance.getName());
2222                 actionResult = Either.right(
2223                     componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(serviceMetadataUpdateResult.right().value())));
2224             } else {
2225                 actionResult = Either
2226                     .left(new ImmutablePair<>(serviceMetadataUpdateResult.left().value(), updateComponentInstanceRes.left().value()));
2227             }
2228         }
2229         return actionResult;
2230     }
2231
2232     private Either<ImmutablePair<Component, User>, ResponseFormat> validateUserAndComponent(String serviceId, User modifier) {
2233         Either<ImmutablePair<Component, User>, ResponseFormat> result = null;
2234         User currUser = null;
2235         Component component = null;
2236         Either<User, ResponseFormat> validationUserResult = validateUserIgnoreAudit(modifier, "updateGroupInstancePropertyValues");
2237         if (validationUserResult.isRight()) {
2238             log.debug("#validateUserAndComponent - Failed to validate user with userId {}, for update service {}. ", modifier.getUserId(), serviceId);
2239             result = Either.right(validationUserResult.right().value());
2240         }
2241         if (result == null) {
2242             currUser = validationUserResult.left().value();
2243             try {
2244                 component = validateComponentExists(serviceId, ComponentTypeEnum.SERVICE, null);
2245                 if (!ComponentValidationUtils.canWorkOnComponent(component, currUser.getUserId())) {
2246                     log.info("#validateUserAndComponent - Restricted operation for user: {}, on service: {}", currUser.getUserId(),
2247                         component.getCreatorUserId());
2248                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
2249                 }
2250             } catch (ComponentException e) {
2251                 log.debug("#validateUserAndComponent - Failed to validate service existing {}. ", serviceId);
2252                 result = Either.right(e.getResponseFormat());
2253             }
2254         }
2255         if (result == null) {
2256             result = Either.left(new ImmutablePair<>(component, currUser));
2257         }
2258         return result;
2259     }
2260
2261     private Either<ImmutablePair<ComponentInstance, GroupInstance>, ResponseFormat> findGroupInstanceOnRelatedComponentInstance(Component component,
2262                                                                                                                                 String componentInstanceId,
2263                                                                                                                                 String groupInstanceId) {
2264         Either<ImmutablePair<ComponentInstance, GroupInstance>, ResponseFormat> actionResult = null;
2265         GroupInstance groupInstance = null;
2266         ComponentInstance foundComponentInstance = findRelatedComponentInstance(component, componentInstanceId);
2267         if (foundComponentInstance == null) {
2268             log.debug("Component instance {} not found on service {}. ", componentInstanceId, component.getName());
2269             actionResult = Either.right(componentsUtils
2270                 .getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, componentInstanceId, "resource instance", "service",
2271                     component.getName()));
2272         } else if (isNotEmpty(foundComponentInstance.getGroupInstances())) {
2273             groupInstance = foundComponentInstance.getGroupInstances().stream().filter(gi -> gi.getUniqueId().equals(groupInstanceId)).findFirst()
2274                 .orElse(null);
2275             if (groupInstance == null) {
2276                 log.debug("Group instance {} not found on component instance {}. ", groupInstanceId, foundComponentInstance.getName());
2277                 actionResult = Either.right(componentsUtils
2278                     .getResponseFormat(ActionStatus.GROUP_INSTANCE_NOT_FOUND_ON_COMPONENT_INSTANCE, groupInstanceId,
2279                         foundComponentInstance.getName()));
2280             }
2281         }
2282         if (actionResult == null) {
2283             actionResult = Either.left(new ImmutablePair<>(foundComponentInstance, groupInstance));
2284         }
2285         return actionResult;
2286     }
2287
2288     private ComponentInstance findRelatedComponentInstance(Component component, String componentInstanceId) {
2289         ComponentInstance componentInstance = null;
2290         if (isNotEmpty(component.getComponentInstances())) {
2291             componentInstance = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(componentInstanceId)).findFirst()
2292                 .orElse(null);
2293         }
2294         return componentInstance;
2295     }
2296
2297     private Either<User, ResponseFormat> validateUserIgnoreAudit(User modifier, String ecompErrorContext) {
2298         User user = validateUser(modifier, ecompErrorContext, null, null, false);
2299         List<Role> roles = new ArrayList<>();
2300         roles.add(Role.ADMIN);
2301         roles.add(Role.DESIGNER);
2302         validateUserRole(user, roles);
2303         return Either.left(user);
2304     }
2305
2306     public Either<UiComponentDataTransfer, ResponseFormat> getUiComponentDataTransferByComponentId(String serviceId,
2307                                                                                                    List<String> dataParamsToReturn) {
2308         ComponentParametersView paramsToReturn = new ComponentParametersView(dataParamsToReturn);
2309         paramsToReturn.setIgnoreComponentInstancesProperties(false);
2310         Either<Service, StorageOperationStatus> serviceResultEither = toscaOperationFacade.getToscaElement(serviceId, paramsToReturn);
2311         if (serviceResultEither.isRight()) {
2312             if (serviceResultEither.right().value() == StorageOperationStatus.NOT_FOUND) {
2313                 log.debug("#getUiComponentDataTransferByComponentId - Failed to find service with id {} ", serviceId);
2314                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SERVICE_NOT_FOUND, serviceId));
2315             }
2316             log.debug("#getUiComponentDataTransferByComponentId - failed to get service by id {} with filters {}", serviceId, dataParamsToReturn);
2317             return Either.right(
2318                 componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(serviceResultEither.right().value()), ""));
2319         }
2320         Service service = serviceResultEither.left().value();
2321         if (dataParamsToReturn.contains(ComponentFieldsEnum.INPUTS.getValue())) {
2322             ListUtils.emptyIfNull(service.getInputs()).stream().filter(input -> CollectionUtils.isEmpty(input.getConstraints()))
2323                 .forEach(input -> input.setConstraints(setInputConstraint(input)));
2324         }
2325         UiComponentDataTransfer dataTransfer = uiComponentDataConverter.getUiDataTransferFromServiceByParams(service, dataParamsToReturn);
2326         return Either.left(dataTransfer);
2327     }
2328
2329     @Autowired(required = false)
2330     public void setServiceCreationPluginList(List<ServiceCreationPlugin> serviceCreationPluginList) {
2331         this.serviceCreationPluginList = serviceCreationPluginList;
2332     }
2333
2334     public boolean isServiceExist(String serviceName) {
2335         return toscaOperationFacade.getLatestByServiceName(serviceName).isLeft();
2336     }
2337
2338     interface ArtifactGenerator<CallVal> extends Callable<Either<CallVal, ResponseFormat>> {
2339
2340     }
2341
2342     @Getter
2343     @AllArgsConstructor(access = AccessLevel.PRIVATE)
2344     class HeatEnvArtifactGenerator implements ArtifactGenerator<ArtifactDefinition> {
2345
2346         private ArtifactDefinition artifactDefinition;
2347         private Service service;
2348         private String resourceInstanceName;
2349         private User modifier;
2350         private boolean shouldLock;
2351         private boolean inTransaction;
2352         private String instanceId;
2353
2354         @Override
2355         public Either<ArtifactDefinition, ResponseFormat> call() throws Exception {
2356             return artifactsBusinessLogic
2357                 .forceGenerateHeatEnvArtifact(artifactDefinition, ComponentTypeEnum.RESOURCE_INSTANCE, service, resourceInstanceName, modifier,
2358                     shouldLock, inTransaction, instanceId);
2359         }
2360     }
2361
2362     @AllArgsConstructor(access = AccessLevel.PRIVATE)
2363     class VfModuleArtifactGenerator implements ArtifactGenerator<ArtifactDefinition> {
2364
2365         private User user;
2366         private ComponentInstance componentInstance;
2367         private Service service;
2368         private boolean shouldLock;
2369         private boolean inTransaction;
2370
2371         private Either<ArtifactDefinition, ResponseFormat> generateVfModuleInstanceArtifact(User modifier, ComponentInstance currVFInstance,
2372                                                                                             Service service, boolean shouldLock,
2373                                                                                             boolean inTransaction) {
2374             ArtifactDefinition vfModuleArtifact = null;
2375             Wrapper<ResponseFormat> responseWrapper = new Wrapper<>();
2376             Wrapper<String> payloadWrapper = new Wrapper<>();
2377             List<GroupInstance> groupsForCurrVF = collectGroupsInstanceForCompInstance(currVFInstance);
2378             if (responseWrapper.isEmpty()) {
2379                 fillVfModuleInstHeatEnvPayload(groupsForCurrVF, payloadWrapper);
2380             }
2381             if (responseWrapper.isEmpty() && payloadWrapper.getInnerElement() != null) {
2382                 vfModuleArtifact = getVfModuleInstArtifactForCompInstance(currVFInstance, service, payloadWrapper, responseWrapper);
2383             }
2384             if (responseWrapper.isEmpty() && vfModuleArtifact != null) {
2385                 vfModuleArtifact = fillVfModulePayload(modifier, currVFInstance, vfModuleArtifact, shouldLock, inTransaction, payloadWrapper,
2386                     responseWrapper, service);
2387             }
2388             if (responseWrapper.isEmpty()) {
2389                 return Either.left(vfModuleArtifact);
2390             } else {
2391                 return Either.right(responseWrapper.getInnerElement());
2392             }
2393         }
2394
2395         private void fillVfModuleInstHeatEnvPayload(List<GroupInstance> groupsForCurrVF, Wrapper<String> payloadWrapper) {
2396             List<VfModuleArtifactPayload> vfModulePayloads = new ArrayList<>();
2397             if (groupsForCurrVF != null) {
2398                 for (GroupInstance groupInstance : groupsForCurrVF) {
2399                     VfModuleArtifactPayload modulePayload = new VfModuleArtifactPayload(groupInstance);
2400                     vfModulePayloads.add(modulePayload);
2401                 }
2402                 vfModulePayloads.sort(VfModuleArtifactPayload::compareByGroupName);
2403                 final Gson gson = new GsonBuilder().setPrettyPrinting().create();
2404                 String vfModulePayloadString = gson.toJson(vfModulePayloads);
2405                 payloadWrapper.setInnerElement(vfModulePayloadString);
2406             }
2407         }
2408
2409         private ArtifactDefinition getVfModuleInstArtifactForCompInstance(ComponentInstance currVF, Service service, Wrapper<String> payloadWrapper,
2410                                                                           Wrapper<ResponseFormat> responseWrapper) {
2411             ArtifactDefinition vfModuleAertifact = null;
2412             if (MapUtils.isNotEmpty(currVF.getDeploymentArtifacts())) {
2413                 final Optional<ArtifactDefinition> optionalVfModuleArtifact = currVF.getDeploymentArtifacts().values().stream()
2414                     .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.VF_MODULES_METADATA.getType())).findAny();
2415                 if (optionalVfModuleArtifact.isPresent()) {
2416                     vfModuleAertifact = optionalVfModuleArtifact.get();
2417                 }
2418             }
2419             if (vfModuleAertifact == null) {
2420                 Either<ArtifactDefinition, ResponseFormat> createVfModuleArtifact = createVfModuleArtifact(currVF, service,
2421                     payloadWrapper.getInnerElement());
2422                 if (createVfModuleArtifact.isLeft()) {
2423                     vfModuleAertifact = createVfModuleArtifact.left().value();
2424                 } else {
2425                     responseWrapper.setInnerElement(createVfModuleArtifact.right().value());
2426                 }
2427             }
2428             return vfModuleAertifact;
2429         }
2430
2431         private List<GroupInstance> collectGroupsInstanceForCompInstance(ComponentInstance currVF) {
2432             if (currVF.getGroupInstances() != null) {
2433                 currVF.getGroupInstances().forEach(gi -> gi.alignArtifactsUuid(currVF.getDeploymentArtifacts()));
2434             }
2435             return currVF.getGroupInstances();
2436         }
2437
2438         private Either<ArtifactDefinition, ResponseFormat> createVfModuleArtifact(ComponentInstance currVF, Service service,
2439                                                                                   String vfModulePayloadString) {
2440             ArtifactDefinition vfModuleArtifactDefinition = new ArtifactDefinition();
2441             String newCheckSum = null;
2442             vfModuleArtifactDefinition.setDescription("Auto-generated VF Modules information artifact");
2443             vfModuleArtifactDefinition.setArtifactDisplayName("Vf Modules Metadata");
2444             vfModuleArtifactDefinition.setArtifactType(ArtifactTypeEnum.VF_MODULES_METADATA.getType());
2445             vfModuleArtifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
2446             vfModuleArtifactDefinition.setArtifactLabel("vfModulesMetadata");
2447             vfModuleArtifactDefinition.setTimeout(0);
2448             vfModuleArtifactDefinition.setArtifactName(currVF.getNormalizedName() + "_modules.json");
2449             vfModuleArtifactDefinition.setPayloadData(vfModulePayloadString);
2450             if (vfModulePayloadString != null) {
2451                 newCheckSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(vfModulePayloadString.getBytes());
2452             }
2453             vfModuleArtifactDefinition.setArtifactChecksum(newCheckSum);
2454             Either<ArtifactDefinition, StorageOperationStatus> addArtifactToComponent = artifactToscaOperation
2455                 .addArtifactToComponent(vfModuleArtifactDefinition, service, NodeTypeEnum.ResourceInstance, true, currVF.getUniqueId());
2456             if (addArtifactToComponent.isLeft()) {
2457                 return Either.left(addArtifactToComponent.left().value());
2458             } else {
2459                 return Either
2460                     .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(addArtifactToComponent.right().value())));
2461             }
2462         }
2463
2464         private ArtifactDefinition fillVfModulePayload(User modifier, ComponentInstance currVF, ArtifactDefinition vfModuleArtifact,
2465                                                        boolean shouldLock,
2466                                                        boolean inTransaction, Wrapper<String> payloadWrapper, Wrapper<ResponseFormat> responseWrapper,
2467                                                        Service service) {
2468             ArtifactDefinition result = null;
2469             Either<ArtifactDefinition, ResponseFormat> eitherPayload = artifactsBusinessLogic
2470                 .generateArtifactPayload(vfModuleArtifact, ComponentTypeEnum.RESOURCE_INSTANCE, service, currVF.getName(), modifier, shouldLock,
2471                     inTransaction, System::currentTimeMillis, () -> Either.left(
2472                         artifactsBusinessLogic.createEsArtifactData(vfModuleArtifact,
2473                             payloadWrapper.getInnerElement().getBytes(StandardCharsets.UTF_8))),
2474                     currVF.getUniqueId());
2475             if (eitherPayload.isLeft()) {
2476                 result = eitherPayload.left().value();
2477             } else {
2478                 responseWrapper.setInnerElement(eitherPayload.right().value());
2479             }
2480             if (result == null) {
2481                 result = vfModuleArtifact;
2482             }
2483             return result;
2484         }
2485
2486         @Override
2487         public Either<ArtifactDefinition, ResponseFormat> call() throws Exception {
2488             return generateVfModuleInstanceArtifact(user, componentInstance, service, shouldLock, inTransaction);
2489         }
2490     }
2491 }