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