Consider component model when retrieving capability types
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / CapabilitiesBusinessLogic.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.openecomp.sdc.be.components.impl;
17
18 import fj.data.Either;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Objects;
26 import java.util.Optional;
27 import java.util.UUID;
28 import java.util.stream.Collectors;
29 import org.apache.commons.collections.CollectionUtils;
30 import org.apache.commons.collections.MapUtils;
31 import org.apache.commons.lang3.StringUtils;
32 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
33 import org.openecomp.sdc.be.components.validation.CapabilitiesValidation;
34 import org.openecomp.sdc.be.config.BeEcompErrorManager;
35 import org.openecomp.sdc.be.dao.api.ActionStatus;
36 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
37 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
38 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
39 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
40 import org.openecomp.sdc.be.model.CapabilityDefinition;
41 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
42 import org.openecomp.sdc.be.model.Component;
43 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
44 import org.openecomp.sdc.be.model.ComponentParametersView;
45 import org.openecomp.sdc.be.model.User;
46 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
47 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.CapabilitiesOperation;
48 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
49 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
50 import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation;
51 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
52 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
53 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
54 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
55 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
56 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
57 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
58 import org.openecomp.sdc.exception.ResponseFormat;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61 import org.springframework.beans.factory.annotation.Autowired;
62
63 @org.springframework.stereotype.Component("capabilitiesBusinessLogic")
64 public class CapabilitiesBusinessLogic extends BaseBusinessLogic {
65
66     private static final Logger LOGGER = LoggerFactory.getLogger(CapabilitiesBusinessLogic.class);
67     private static final String FAILED_TO_LOCK_COMPONENT_RESPONSE_IS = "Failed to lock component {}. Response is {}";
68     private static final String DELETE_CAPABILITIES = "deleteCapability";
69     private static final String GET_CAPABILITIES = "getCapabilities";
70     private static final String EXCEPTION_OCCURRED_DURING_CAPABILITIES = "Exception occurred during {}. Response is {}";
71     private final ICapabilityTypeOperation capabilityTypeOperation;
72     private CapabilitiesOperation capabilitiesOperation;
73     private CapabilitiesValidation capabilitiesValidation;
74
75     @Autowired
76     public CapabilitiesBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
77                                      IGroupTypeOperation groupTypeOperation, GroupBusinessLogic groupBusinessLogic,
78                                      InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
79                                      ICapabilityTypeOperation capabilityTypeOperation, ArtifactsOperations artifactToscaOperation) {
80         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
81             artifactToscaOperation);
82         this.capabilityTypeOperation = capabilityTypeOperation;
83     }
84
85     @Autowired
86     public void setCapabilitiesValidation(CapabilitiesValidation capabilitiesValidation) {
87         this.capabilitiesValidation = capabilitiesValidation;
88     }
89
90     @Autowired
91     public void setCapabilitiesOperation(CapabilitiesOperation capabilitiesOperation) {
92         this.capabilitiesOperation = capabilitiesOperation;
93     }
94
95     public Either<List<CapabilityDefinition>, ResponseFormat> createCapabilities(String componentId, List<CapabilityDefinition> capabilityDefinitions,
96                                                                                  User user, String errorContext, boolean lock) {
97         Either<Component, ResponseFormat> validateUserAndCapabilitiesEither = validateUserAndCapabilities(user, componentId, errorContext,
98             capabilityDefinitions);
99         if (validateUserAndCapabilitiesEither.isRight()) {
100             return Either.right(validateUserAndCapabilitiesEither.right().value());
101         }
102         Component storedComponent = validateUserAndCapabilitiesEither.left().value();
103         Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock, storedComponent, errorContext);
104         if (lockResult.isRight()) {
105             return Either.right(lockResult.right().value());
106         }
107         try {
108             return createCapability(componentId, capabilityDefinitions, storedComponent);
109         } catch (Exception e) {
110             janusGraphDao.rollback();
111             LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "addOrUpdate", e);
112             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
113         } finally {
114             if (lockResult.isLeft() && lockResult.left().value()) {
115                 graphLockOperation
116                     .unlockComponent(storedComponent.getUniqueId(), NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
117             }
118         }
119     }
120
121     private Either<Component, ResponseFormat> validateUserAndCapabilities(User user, String componentId, String errorContext,
122                                                                           List<CapabilityDefinition> capabilityDefinitions) {
123         validateUserExists(user.getUserId());
124         Either<Component, ResponseFormat> componentEither = getComponentDetails(componentId);
125         if (componentEither.isRight()) {
126             return Either.right(componentEither.right().value());
127         }
128         Component storedComponent = componentEither.left().value();
129         Either<Boolean, ResponseFormat> capabilitiesValidationEither = capabilitiesValidation
130             .validateCapabilities(capabilityDefinitions, storedComponent, false);
131         if (capabilitiesValidationEither.isRight()) {
132             return Either.right(capabilitiesValidationEither.right().value());
133         }
134         return Either.left(storedComponent);
135     }
136
137     private Either<List<CapabilityDefinition>, ResponseFormat> createCapability(String componentId, List<CapabilityDefinition> capabilityDefinitions,
138                                                                                 Component storedComponent) {
139         Either<List<CapabilityDefinition>, StorageOperationStatus> result;
140         List<CapabilityDefinition> capabilitiesListStoredInComponent = null;
141         Map<String, List<CapabilityDefinition>> storedComponentCapabilities = storedComponent.getCapabilities();
142         if (MapUtils.isNotEmpty(storedComponentCapabilities)) {
143             CapabilityDefinition capabilityDefinitionToGetType = capabilityDefinitions.get(0);
144             if (Objects.isNull(capabilityDefinitionToGetType)) {
145                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
146             }
147             capabilitiesListStoredInComponent = getCapabilityStoredInComponentByType(capabilityDefinitionToGetType.getType(),
148                 storedComponentCapabilities);
149         }
150         List<CapabilityDefinition> capabilitiesDefListToCreate;
151         List<CapabilityDefinition> capabilitiesToReturn;
152         if (CollectionUtils.isNotEmpty(capabilitiesListStoredInComponent)) {
153             capabilitiesDefListToCreate = capabilityDefinitions.stream()
154                 .map(capabilityDefinition -> initiateNewCapability(storedComponent, capabilityDefinition)).collect(Collectors.toList());
155             capabilitiesToReturn = capabilitiesDefListToCreate;
156             capabilitiesDefListToCreate.addAll(capabilitiesListStoredInComponent);
157             result = capabilitiesOperation.updateCapabilities(componentId, capabilitiesDefListToCreate);
158         } else {
159             capabilitiesToReturn = capabilityDefinitions.stream()
160                 .map(capabilityDefinition -> initiateNewCapability(storedComponent, capabilityDefinition)).collect(Collectors.toList());
161             result = capabilitiesOperation.addCapabilities(componentId, capabilitiesToReturn);
162         }
163         if (result.isRight()) {
164             janusGraphDao.rollback();
165             return Either.right(componentsUtils
166                 .getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value(), storedComponent.getComponentType()), ""));
167         }
168         Map<String, MapPropertiesDataDefinition> propertiesMap = getCapabilitiesPropertiesDataDefinitionMap(capabilityDefinitions);
169         if (MapUtils.isNotEmpty(propertiesMap)) {
170             StorageOperationStatus storageOperationStatus = capabilitiesOperation.createOrUpdateCapabilityProperties(componentId, propertiesMap);
171             if (storageOperationStatus != StorageOperationStatus.OK) {
172                 janusGraphDao.rollback();
173                 return Either.right(componentsUtils.getResponseFormat(storageOperationStatus));
174             }
175         }
176         janusGraphDao.commit();
177         return Either.left(capabilitiesToReturn);
178     }
179
180     public Either<List<CapabilityDefinition>, ResponseFormat> updateCapabilities(String componentId, List<CapabilityDefinition> capabilityDefinitions,
181                                                                                  User user, String errorContext, boolean lock) {
182         validateUserExists(user.getUserId());
183         Either<Component, ResponseFormat> componentEither = getComponentDetails(componentId);
184         if (componentEither.isRight()) {
185             return Either.right(componentEither.right().value());
186         }
187         Component storedComponent = componentEither.left().value();
188         Either<Boolean, ResponseFormat> capabilitiesValidationEither = capabilitiesValidation
189             .validateCapabilities(capabilityDefinitions, storedComponent, true);
190         if (capabilitiesValidationEither.isRight()) {
191             return Either.right(capabilitiesValidationEither.right().value());
192         }
193         Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock, storedComponent, errorContext);
194         if (lockResult.isRight()) {
195             return Either.right(lockResult.right().value());
196         }
197         try {
198             Either<List<CapabilityDefinition>, StorageOperationStatus> result;
199             List<CapabilityDefinition> capabilitiesListStoredInComponent = null;
200             Map<String, List<CapabilityDefinition>> storedComponentCapabilities = storedComponent.getCapabilities();
201             if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentCapabilities)) {
202                 CapabilityDefinition capabilityDefinitionToGetType = capabilityDefinitions.get(0);
203                 if (Objects.isNull(capabilityDefinitionToGetType)) {
204                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
205                 }
206                 capabilitiesListStoredInComponent = getCapabilityStoredInComponentByType(capabilityDefinitionToGetType.getType(),
207                     storedComponentCapabilities);
208             }
209             List<CapabilityDefinition> capabilitiesDefListToUpdate = new ArrayList<>();
210             List<CapabilityDefinition> capabilitiesToReturn = null;
211             if (CollectionUtils.isNotEmpty(capabilitiesListStoredInComponent)) {
212                 if (capabilityDefinitions.stream()
213                     .anyMatch(capabilityDefinition -> isCapabilityUsedInServiceComposition(capabilityDefinition, storedComponent))) {
214                     LOGGER.error("Capability can't be edited, since it is" + " used in service composition");
215                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION));
216                 }
217                 for (CapabilityDefinition capabilityDefinitionToUpdate : capabilityDefinitions) {
218                     capabilitiesToReturn = capabilitiesListStoredInComponent.stream()
219                         .filter(capToUpdate -> capToUpdate.getUniqueId().equals(capabilityDefinitionToUpdate.getUniqueId()))
220                         .map(capabilityDefinition -> updateCapability(capabilityDefinition, capabilityDefinitionToUpdate, storedComponent))
221                         .collect(Collectors.toList());
222                     capabilitiesListStoredInComponent
223                         .removeIf(capToUpdate -> capToUpdate.getUniqueId().equals(capabilityDefinitionToUpdate.getUniqueId()));
224                     if (CollectionUtils.isNotEmpty(capabilitiesToReturn)) {
225                         capabilitiesListStoredInComponent.addAll(capabilitiesToReturn);
226                         capabilitiesDefListToUpdate.addAll(capabilitiesListStoredInComponent);
227                     } else {
228                         Either<List<CapabilityDefinition>, ResponseFormat> capTypeUpdateEither = handleCapabilityTypeUpdateWhenNewTypeExist(
229                             storedComponent, storedComponent.getCapabilities(), capabilitiesToReturn, capabilityDefinitionToUpdate);
230                         if (capTypeUpdateEither.isRight()) {
231                             return Either.right(capTypeUpdateEither.right().value());
232                         }
233                         capabilitiesDefListToUpdate = capTypeUpdateEither.left().value();
234                     }
235                 }
236                 result = capabilitiesOperation.updateCapabilities(componentId, capabilitiesDefListToUpdate);
237             } else {
238                 Either<List<CapabilityDefinition>, ResponseFormat> capabilityDefinitionToDelete = handleCapabilityTypeUpdateWhenNewTypeNotExist(
239                     capabilityDefinitions, storedComponent, storedComponentCapabilities);
240                 if (capabilityDefinitionToDelete != null) {
241                     return capabilityDefinitionToDelete;
242                 }
243                 capabilitiesToReturn = capabilityDefinitions.stream()
244                     .map(capabilityDefinition -> initiateNewCapability(storedComponent, capabilityDefinition)).collect(Collectors.toList());
245                 result = capabilitiesOperation.addCapabilities(componentId, capabilitiesToReturn);
246             }
247             if (result.isRight()) {
248                 janusGraphDao.rollback();
249                 return Either.right(componentsUtils
250                     .getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value(), storedComponent.getComponentType()), ""));
251             }
252             Map<String, MapPropertiesDataDefinition> propertiesMap = getCapabilitiesPropertiesDataDefinitionMap(capabilityDefinitions);
253             if (MapUtils.isNotEmpty(propertiesMap)) {
254                 StorageOperationStatus storageOperationStatus = capabilitiesOperation.createOrUpdateCapabilityProperties(componentId, propertiesMap);
255                 if (storageOperationStatus != StorageOperationStatus.OK) {
256                     janusGraphDao.rollback();
257                     return Either.right(componentsUtils.getResponseFormat(storageOperationStatus));
258                 }
259             }
260             janusGraphDao.commit();
261             return Either.left(capabilitiesToReturn);
262         } catch (Exception e) {
263             janusGraphDao.rollback();
264             LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "addOrUpdate", e);
265             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
266         } finally {
267             if (lockResult.isLeft() && lockResult.left().value()) {
268                 graphLockOperation
269                     .unlockComponent(storedComponent.getUniqueId(), NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
270             }
271         }
272     }
273
274     private Either<List<CapabilityDefinition>, ResponseFormat> handleCapabilityTypeUpdateWhenNewTypeExist(Component storedComponent,
275                                                                                                           Map<String, List<CapabilityDefinition>> storedComponentCapabilities,
276                                                                                                           List<CapabilityDefinition> capabilitiesToReturn,
277                                                                                                           CapabilityDefinition capabilityDefinitionToUpdate) {
278         List<CapabilityDefinition> capabilitiesListStoredInComponent;
279         List<CapabilityDefinition> capabilitiesDefsToCreateOrUpdate = new ArrayList<>();
280         Optional<CapabilityDefinition> definitionOptional = storedComponentCapabilities.values().stream().flatMap(Collection::stream)
281             .filter(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(capabilityDefinitionToUpdate.getUniqueId())).findAny();
282         if (!definitionOptional.isPresent()) {
283             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId()));
284         }
285         CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get();
286         capabilitiesListStoredInComponent = getCapabilityStoredInComponentByType(capabilityDefinitionToUpdate.getType(), storedComponentCapabilities);
287         Either<List<CapabilityDefinition>, StorageOperationStatus> deleteCapabilityEither = deleteCapability(storedComponent,
288             storedComponentCapabilities, capabilityDefinitionToDelete);
289         if (deleteCapabilityEither.isRight()) {
290             janusGraphDao.rollback();
291             return Either.right(componentsUtils.getResponseFormat(deleteCapabilityEither.right().value()));
292         }
293         StorageOperationStatus deleteStorageOperationStatus = capabilitiesOperation
294             .deleteCapabilityProperties(storedComponent, buildCapPropKey(capabilityDefinitionToDelete));
295         if (deleteStorageOperationStatus != StorageOperationStatus.OK) {
296             janusGraphDao.rollback();
297             return Either.right(componentsUtils.getResponseFormat(deleteStorageOperationStatus));
298         }
299         capabilitiesToReturn.add(initiateNewCapability(storedComponent, capabilityDefinitionToUpdate));
300         capabilitiesDefsToCreateOrUpdate.addAll(capabilitiesToReturn);
301         capabilitiesDefsToCreateOrUpdate.addAll(capabilitiesListStoredInComponent);
302         return Either.left(capabilitiesDefsToCreateOrUpdate);
303     }
304
305     private Either<List<CapabilityDefinition>, ResponseFormat> handleCapabilityTypeUpdateWhenNewTypeNotExist(
306         List<CapabilityDefinition> capabilityDefinitions, Component storedComponent,
307         Map<String, List<CapabilityDefinition>> storedComponentCapabilities) {
308         for (CapabilityDefinition capabilityDefinitionToUpdate : capabilityDefinitions) {
309             Optional<CapabilityDefinition> definitionOptional = storedComponentCapabilities.values().stream().flatMap(Collection::stream)
310                 .filter(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(capabilityDefinitionToUpdate.getUniqueId())).findAny();
311             if (!definitionOptional.isPresent()) {
312                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId()));
313             }
314             CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get();
315             Boolean isCapabilityUsedInServiceComposition = isCapabilityUsedInServiceComposition(capabilityDefinitionToDelete, storedComponent);
316             if (isCapabilityUsedInServiceComposition) {
317                 LOGGER.error("Capability {} can't be edited, since it is used in service composition", capabilityDefinitionToDelete.getUniqueId());
318                 return Either.right(componentsUtils
319                     .getResponseFormat(ActionStatus.CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION, capabilityDefinitionToDelete.getName()));
320             }
321             Either<List<CapabilityDefinition>, StorageOperationStatus> deleteCapabilityEither = deleteCapability(storedComponent,
322                 storedComponentCapabilities, capabilityDefinitionToDelete);
323             if (deleteCapabilityEither.isRight()) {
324                 janusGraphDao.rollback();
325                 return Either.right(componentsUtils.getResponseFormat(deleteCapabilityEither.right().value()));
326             }
327             StorageOperationStatus deleteStorageOperationStatus = capabilitiesOperation
328                 .deleteCapabilityProperties(storedComponent, buildCapPropKey(capabilityDefinitionToDelete));
329             if (deleteStorageOperationStatus != StorageOperationStatus.OK) {
330                 janusGraphDao.rollback();
331                 return Either.right(componentsUtils.getResponseFormat(deleteStorageOperationStatus));
332             }
333         }
334         return null;
335     }
336
337     public Either<CapabilityDefinition, ResponseFormat> getCapability(String componentId, String capabilityToGet, User user, boolean lock) {
338         validateUserExists(user.getUserId());
339         Either<Component, ResponseFormat> componentEither = getComponentDetails(componentId);
340         if (componentEither.isRight()) {
341             return Either.right(componentEither.right().value());
342         }
343         Component storedComponent = componentEither.left().value();
344         Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock, storedComponent, GET_CAPABILITIES);
345         if (lockResult.isRight()) {
346             return Either.right(lockResult.right().value());
347         }
348         try {
349             Either<CapabilityDefinition, ResponseFormat> getCapabilityDefinitionEither = getCapabilityDefinition(capabilityToGet, storedComponent);
350             if (getCapabilityDefinitionEither.isRight()) {
351                 return Either.right(getCapabilityDefinitionEither.right().value());
352             }
353             return Either.left(getCapabilityDefinitionEither.left().value());
354         } catch (Exception e) {
355             LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "get", e);
356             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, componentId));
357         } finally {
358             if (lockResult.isLeft() && lockResult.left().value()) {
359                 graphLockOperation
360                     .unlockComponent(storedComponent.getUniqueId(), NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
361             }
362         }
363     }
364
365     private Either<CapabilityDefinition, ResponseFormat> getCapabilityDefinition(String capabilityIdToGet, Component storedComponent) {
366         List<CapabilityDefinition> capabilityDefinitions = storedComponent.getCapabilities().values().stream().flatMap(Collection::stream)
367             .collect(Collectors.toList());
368         if (capabilityDefinitions.isEmpty()) {
369             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId()));
370         }
371         CapabilityDefinition capabilityDefinitionToReturn;
372         Optional<CapabilityDefinition> capabilityDefinitionOptional = capabilityDefinitions.stream()
373             .filter(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(capabilityIdToGet)).findAny();
374         if (capabilityDefinitionOptional.isPresent()) {
375             capabilityDefinitionToReturn = capabilityDefinitionOptional.get();
376         } else {
377             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId()));
378         }
379         return Either.left(capabilityDefinitionToReturn);
380     }
381
382     public Either<CapabilityDefinition, ResponseFormat> deleteCapability(String componentId, String capabilityIdToDelete, User user, boolean lock) {
383         validateUserExists(user.getUserId());
384         Either<Component, ResponseFormat> componentEither = getComponentDetails(componentId);
385         if (componentEither.isRight()) {
386             return Either.right(componentEither.right().value());
387         }
388         Component storedComponent = componentEither.left().value();
389         Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock, storedComponent, DELETE_CAPABILITIES);
390         if (lockResult.isRight()) {
391             return Either.right(lockResult.right().value());
392         }
393         try {
394             return deleteCapability(capabilityIdToDelete, storedComponent);
395         } catch (Exception e) {
396             LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "delete", e);
397             janusGraphDao.rollback();
398             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND));
399         } finally {
400             if (lockResult.isLeft() && lockResult.left().value()) {
401                 graphLockOperation
402                     .unlockComponent(storedComponent.getUniqueId(), NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
403             }
404         }
405     }
406
407     private Either<CapabilityDefinition, ResponseFormat> deleteCapability(String capabilityIdToDelete, Component storedComponent) {
408         Map<String, List<CapabilityDefinition>> storedComponentCapabilities = storedComponent.getCapabilities();
409         if (storedComponentCapabilities.isEmpty()) {
410             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId()));
411         }
412         Either<CapabilityDefinition, ResponseFormat> capabilityDefinitionToDeleteEither = getAndValidateCapabilitiesToDelete(storedComponent,
413             storedComponentCapabilities, capabilityIdToDelete);
414         if (capabilityDefinitionToDeleteEither.isRight()) {
415             return Either.right(capabilityDefinitionToDeleteEither.right().value());
416         }
417         Either<List<CapabilityDefinition>, StorageOperationStatus> result = deleteCapability(storedComponent, storedComponentCapabilities,
418             capabilityDefinitionToDeleteEither.left().value());
419         if (result.isRight()) {
420             janusGraphDao.rollback();
421             LOGGER.error("Failed to delete capability  from component {}. Response is {}", storedComponent.getName(), result.right().value());
422             return Either.right(componentsUtils
423                 .getResponseFormat(componentsUtils.convertFromStorageResponse(result.right().value(), storedComponent.getComponentType())));
424         }
425         janusGraphDao.commit();
426         return Either.left(capabilityDefinitionToDeleteEither.left().value());
427     }
428
429     private Either<CapabilityDefinition, ResponseFormat> getAndValidateCapabilitiesToDelete(Component storedComponent,
430                                                                                             Map<String, List<CapabilityDefinition>> storedComponentCapabilities,
431                                                                                             String capabilityIdToDelete) {
432         Optional<CapabilityDefinition> definitionOptional = storedComponentCapabilities.values().stream().flatMap(Collection::stream)
433             .filter(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(capabilityIdToDelete)).findAny();
434         if (!definitionOptional.isPresent()) {
435             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId()));
436         }
437         CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get();
438         Boolean isCapabilityUsedInServiceComposition = isCapabilityUsedInServiceComposition(capabilityDefinitionToDelete, storedComponent);
439         if (isCapabilityUsedInServiceComposition) {
440             LOGGER.error("Capability {} can't be deleted, since it is used in service composition", capabilityDefinitionToDelete.getUniqueId());
441             return Either.right(componentsUtils
442                 .getResponseFormat(ActionStatus.CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION, capabilityDefinitionToDelete.getName()));
443         }
444         return Either.left(capabilityDefinitionToDelete);
445     }
446
447     private Either<List<CapabilityDefinition>, StorageOperationStatus> deleteCapability(Component storedComponent,
448                                                                                         Map<String, List<CapabilityDefinition>> storedComponentCapabilities,
449                                                                                         CapabilityDefinition capabilityDefinitionToDelete) {
450         List<CapabilityDefinition> capabilitiesListStoredInComponent = getCapabilityStoredInComponentByType(capabilityDefinitionToDelete.getType(),
451             storedComponentCapabilities);
452         capabilitiesListStoredInComponent
453             .removeIf(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(capabilityDefinitionToDelete.getUniqueId()));
454         Either<List<CapabilityDefinition>, StorageOperationStatus> result;
455         if (capabilitiesListStoredInComponent.isEmpty()) {
456             StorageOperationStatus operationStatus = capabilitiesOperation
457                 .deleteCapabilities(storedComponent, capabilityDefinitionToDelete.getType());
458             if (StorageOperationStatus.OK.equals(operationStatus)) {
459                 result = Either.left(Collections.singletonList(capabilityDefinitionToDelete));
460             } else {
461                 result = Either.right(operationStatus);
462             }
463         } else {
464             result = capabilitiesOperation.updateCapabilities(storedComponent.getUniqueId(), capabilitiesListStoredInComponent);
465         }
466         if (result.isLeft()) {
467             StorageOperationStatus deleteStorageOperationStatus = capabilitiesOperation
468                 .deleteCapabilityProperties(storedComponent, buildCapPropKey(capabilityDefinitionToDelete));
469             if (deleteStorageOperationStatus != StorageOperationStatus.OK) {
470                 result = Either.right(deleteStorageOperationStatus);
471             }
472         }
473         return result;
474     }
475
476     private Either<Component, ResponseFormat> getComponentDetails(String componentId) {
477         ComponentParametersView filter = new ComponentParametersView(true);
478         filter.setIgnoreCapabilities(false);
479         filter.setIgnoreCapabiltyProperties(false);
480         Either<Component, StorageOperationStatus> componentStorageOperationStatusEither = toscaOperationFacade.getToscaElement(componentId, filter);
481         if (componentStorageOperationStatusEither.isRight()) {
482             StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value();
483             LOGGER.error("Failed to fetch component information by component id {}, Response is {}", componentId, errorStatus);
484             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
485         }
486         return Either.left(componentStorageOperationStatusEither.left().value());
487     }
488
489     private Either<Boolean, ResponseFormat> lockComponentResult(boolean lock, Component component, String action) {
490         if (lock) {
491             try {
492                 lockComponent(component.getUniqueId(), component, action);
493             } catch (ComponentException e) {
494                 LOGGER.debug(FAILED_TO_LOCK_COMPONENT_RESPONSE_IS, component.getName(), e.getMessage());
495                 janusGraphDao.rollback();
496                 throw e;
497             }
498         }
499         return Either.left(true);
500     }
501
502     private List<CapabilityDefinition> getCapabilityStoredInComponentByType(String capabilityType,
503                                                                             Map<String, List<CapabilityDefinition>> capabilities) {
504         Optional<Map.Entry<String, List<CapabilityDefinition>>> entryOptional = capabilities.entrySet().stream()
505             .filter(map -> map.getKey().equals(capabilityType)).findFirst();
506         return entryOptional.map(Map.Entry::getValue).orElse(Collections.emptyList());
507     }
508
509     private CapabilityDefinition initiateNewCapability(Component component, CapabilityDefinition capabilityDefinition) {
510         if (StringUtils.isEmpty(capabilityDefinition.getUniqueId())) {
511             capabilityDefinition.setUniqueId(UUID.randomUUID().toString());
512         }
513         if (StringUtils.isEmpty(capabilityDefinition.getOwnerId())) {
514             capabilityDefinition.setOwnerId(component.getUniqueId());
515         }
516         if (StringUtils.isEmpty(capabilityDefinition.getOwnerName())) {
517             capabilityDefinition.setOwnerName(component.getName());
518         }
519         capabilityDefinition.setLeftOccurrences(capabilityDefinition.getMaxOccurrences());
520         List<ComponentInstanceProperty> capabilityProperties = capabilityDefinition.getProperties();
521         initiateProperties(capabilityDefinition, capabilityProperties);
522         return capabilityDefinition;
523     }
524
525     private void initiateProperties(CapabilityDefinition capabilityDefinition, List<ComponentInstanceProperty> capabilityProperties) {
526         if (CollectionUtils.isNotEmpty(capabilityProperties)) {
527             capabilityProperties.stream().filter(prop -> prop != null && StringUtils.isEmpty(prop.getUniqueId())).forEach(propDef -> {
528                 String uid = UniqueIdBuilder.buildRequirementUid(capabilityDefinition.getUniqueId(), propDef.getName());
529                 propDef.setUniqueId(uid);
530                 propDef.setParentUniqueId(capabilityDefinition.getUniqueId());
531             });
532         }
533     }
534
535     private CapabilityDefinition updateCapability(CapabilityDefinition storedCapability, CapabilityDefinition capabilityToUpdate,
536                                                   Component component) {
537         storedCapability.setName(capabilityToUpdate.getName());
538         storedCapability.setDescription(capabilityToUpdate.getDescription());
539         storedCapability.setType(capabilityToUpdate.getType());
540         storedCapability.setValidSourceTypes(capabilityToUpdate.getValidSourceTypes());
541         storedCapability.setMinOccurrences(capabilityToUpdate.getMinOccurrences());
542         storedCapability.setMaxOccurrences(capabilityToUpdate.getMaxOccurrences());
543         if (!storedCapability.getType().equals(capabilityToUpdate.getType())) {
544             List<ComponentInstanceProperty> capabilityProperties = capabilityToUpdate.getProperties();
545             initiateProperties(capabilityToUpdate, capabilityProperties);
546             storedCapability.setProperties(capabilityToUpdate.getProperties());
547         }
548         if (!storedCapability.getName().equals(capabilityToUpdate.getName())) {
549             StorageOperationStatus deleteStorageOperationStatus = capabilitiesOperation
550                 .deleteCapabilityProperties(component, buildCapPropKey(storedCapability));
551             if (deleteStorageOperationStatus != StorageOperationStatus.OK) {
552                 janusGraphDao.rollback();
553             }
554         }
555         return storedCapability;
556     }
557
558     private Boolean isCapabilityUsedInServiceComposition(CapabilityDefinition capabilityDefinition, Component component) {
559         Either<List<Component>, StorageOperationStatus> componentList = toscaOperationFacade.getParentComponents(component.getUniqueId());
560         if (componentList.isRight()) {
561             return Boolean.FALSE;
562         }
563         return componentList.left().value().stream().flatMap(parentComponent -> parentComponent.getComponentInstancesRelations().stream())
564             .flatMap(requirementCapabilityRelDef -> requirementCapabilityRelDef.getRelationships().stream()).anyMatch(
565                 capabilityRequirementRelationship -> capabilityRequirementRelationship.getRelation().getCapabilityUid()
566                     .equals(capabilityDefinition.getUniqueId()));
567     }
568
569     public Either<Map<String, CapabilityTypeDefinition>, ResponseFormat> getAllCapabilityTypes(String modelName) {
570         Either<Map<String, CapabilityTypeDefinition>, JanusGraphOperationStatus> capabilityTypeCacheAll = capabilityTypeOperation
571             .getAllCapabilityTypes(modelName);
572         if (capabilityTypeCacheAll.isRight()) {
573             JanusGraphOperationStatus operationStatus = capabilityTypeCacheAll.right().value();
574             if (JanusGraphOperationStatus.NOT_FOUND == operationStatus) {
575                 BeEcompErrorManager.getInstance()
576                     .logInternalDataError("FetchCapabilityTypes", "Capability types are not loaded", BeEcompErrorManager.ErrorSeverity.ERROR);
577                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY));
578             } else {
579                 BeEcompErrorManager.getInstance()
580                     .logInternalFlowError("FetchCapabilityTypes", "Failed to fetch capability types", BeEcompErrorManager.ErrorSeverity.ERROR);
581                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
582             }
583         }
584         return Either.left(capabilityTypeCacheAll.left().value());
585     }
586
587     private Map<String, MapPropertiesDataDefinition> getCapabilitiesPropertiesDataDefinitionMap(List<CapabilityDefinition> capabilityDefinitions) {
588         CapabilityDefinition capabilityDefinitionToAddOrUpdateCapProp = capabilityDefinitions.get(0);
589         List<ComponentInstanceProperty> componentInstanceProperties = null;
590         if (Objects.nonNull(capabilityDefinitionToAddOrUpdateCapProp)) {
591             componentInstanceProperties = capabilityDefinitionToAddOrUpdateCapProp.getProperties();
592         }
593         Map<String, MapPropertiesDataDefinition> propertiesMap = new HashMap<>();
594         if (CollectionUtils.isNotEmpty(componentInstanceProperties)) {
595             MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition();
596             for (ComponentInstanceProperty cip : componentInstanceProperties) {
597                 dataToCreate.put(cip.getName(), new PropertyDataDefinition(cip));
598             }
599             propertiesMap.put(buildCapPropKey(capabilityDefinitionToAddOrUpdateCapProp), dataToCreate);
600         }
601         return propertiesMap;
602     }
603
604     private String buildCapPropKey(CapabilityDefinition capabilityDefinitionToAddOrUpdateCapProp) {
605         return capabilityDefinitionToAddOrUpdateCapProp.getType() + ModelConverter.CAP_PROP_DELIM + capabilityDefinitionToAddOrUpdateCapProp
606             .getName();
607     }
608 }