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