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