Add node_filter capabilities
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ComponentNodeFilterBusinessLogic.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2020 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
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  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.openecomp.sdc.be.components.impl;
21
22 import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR;
23
24 import fj.data.Either;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Optional;
29 import java.util.stream.Collectors;
30 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
31 import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction;
32 import org.openecomp.sdc.be.components.validation.NodeFilterValidator;
33 import org.openecomp.sdc.be.dao.api.ActionStatus;
34 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
35 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
36 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
37 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
38 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
39 import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType;
40 import org.openecomp.sdc.be.model.Component;
41 import org.openecomp.sdc.be.model.ComponentInstance;
42 import org.openecomp.sdc.be.model.User;
43 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
44 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
45 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeFilterOperation;
46 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
47 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
48 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
49 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
50 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
51 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
52 import org.openecomp.sdc.be.user.Role;
53 import org.openecomp.sdc.common.log.wrappers.Logger;
54 import org.openecomp.sdc.exception.ResponseFormat;
55 import org.springframework.beans.factory.annotation.Autowired;
56
57 @org.springframework.stereotype.Component("componentNodeFilterBusinessLogic")
58 public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic {
59
60     private static final Logger LOGGER = Logger.getLogger(ComponentNodeFilterBusinessLogic.class.getName());
61
62     private final NodeFilterOperation nodeFilterOperation;
63     private final NodeFilterValidator nodeFilterValidator;
64
65     @Autowired
66     public ComponentNodeFilterBusinessLogic(final IElementOperation elementDao,
67                                             final IGroupOperation groupOperation,
68                                             final IGroupInstanceOperation groupInstanceOperation,
69                                             final IGroupTypeOperation groupTypeOperation,
70                                             final InterfaceOperation interfaceOperation,
71                                             final InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
72                                             final ArtifactsOperations artifactToscaOperation,
73                                             final NodeFilterOperation nodeFilterOperation,
74                                             final NodeFilterValidator nodeFilterValidator) {
75         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation,
76             interfaceLifecycleTypeOperation, artifactToscaOperation);
77         this.nodeFilterOperation = nodeFilterOperation;
78         this.nodeFilterValidator = nodeFilterValidator;
79     }
80
81     public Optional<CINodeFilterDataDefinition> createNodeFilterIfNotExist(final String componentId,
82                                                                            final String componentInstanceId,
83                                                                            final boolean shouldLock,
84                                                                            final ComponentTypeEnum componentTypeEnum)
85         throws BusinessLogicException {
86
87         final Component component = getComponent(componentId);
88         final Optional<ComponentInstance> componentInstance = getComponentInstance(componentInstanceId, component);
89         Optional<CINodeFilterDataDefinition> filterDataDefinition = getCiNodeFilterDataDefinition(componentInstance);
90         if (filterDataDefinition.isPresent()) {
91             return filterDataDefinition;
92         }
93         final Either<CINodeFilterDataDefinition, StorageOperationStatus> result;
94         boolean wasLocked = false;
95         try {
96             if (shouldLock) {
97                 lockComponent(component.getUniqueId(), component,"Create Node Filter on component");
98                 wasLocked = true;
99             }
100             result = nodeFilterOperation.createNodeFilter(componentId, componentInstanceId);
101             if (result.isRight()) {
102                 janusGraphDao.rollback();
103                 LOGGER.error(BUSINESS_PROCESS_ERROR,
104                     "Failed to Create Node filter on component with id {}", componentId);
105                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
106                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
107             } else {
108                 filterDataDefinition = Optional.ofNullable(result.left().value());
109             }
110             janusGraphDao.commit();
111             LOGGER.debug("Node filter successfully created in component {} . ", component.getSystemName());
112
113         } catch (final Exception e) {
114             janusGraphDao.rollback();
115             LOGGER.error(BUSINESS_PROCESS_ERROR,
116                 "Exception occurred during add Component node filter property values: {}", e.getMessage(), e);
117             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
118
119         } finally {
120             if (wasLocked) {
121                 unlockComponent(component.getUniqueId(), componentTypeEnum);
122             }
123         }
124         return filterDataDefinition;
125     }
126
127     public Optional<String> deleteNodeFilterIfExists(final String componentId,
128                                                      final String componentInstanceId,
129                                                      final boolean shouldLock,
130                                                      final ComponentTypeEnum componentTypeEnum)
131         throws BusinessLogicException {
132
133         final Component component = getComponent(componentId);
134         final Optional<CINodeFilterDataDefinition> nodeFilterDataDefinition =
135             getCiNodeFilterDataDefinition(componentInstanceId, component);
136         if (!nodeFilterDataDefinition.isPresent()) {
137             return Optional.ofNullable(componentInstanceId);
138         }
139
140         final Either<String, StorageOperationStatus> result;
141         boolean wasLocked = false;
142         try {
143             if (shouldLock) {
144                 lockComponent(component.getUniqueId(), component,"Delete Node Filter from component");
145                 wasLocked = true;
146             }
147             result = nodeFilterOperation.deleteNodeFilter(component, componentInstanceId);
148             if (result.isRight()) {
149                 LOGGER.error(BUSINESS_PROCESS_ERROR,
150                     "Failed to delete node filter in component {}. Response is {}. ", component.getName(),
151                     result.right().value());
152                 janusGraphDao.rollback();
153                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
154                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
155             }
156             janusGraphDao.commit();
157             LOGGER.debug("Node filter successfully deleted in component {} . ", component.getSystemName());
158
159         } catch (final Exception e) {
160             LOGGER.error(BUSINESS_PROCESS_ERROR,"Exception occurred during delete deleting node filter: {}",
161                 e.getMessage(), e);
162             janusGraphDao.rollback();
163             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
164         } finally {
165             if (wasLocked) {
166                 unlockComponent(component.getUniqueId(), componentTypeEnum);
167             }
168         }
169         return Optional.ofNullable(result.left().value());
170     }
171
172     public Optional<CINodeFilterDataDefinition> addNodeFilter(final String componentId,
173                                                               final String componentInstanceId,
174                                                               final NodeFilterConstraintAction action,
175                                                               final String propertyName,
176                                                               final String constraint,
177                                                               final boolean shouldLock,
178                                                               final ComponentTypeEnum componentTypeEnum,
179                                                               final NodeFilterConstraintType nodeFilterConstraintType)
180         throws BusinessLogicException {
181
182         final Component component = getComponent(componentId);
183         CINodeFilterDataDefinition nodeFilterDataDefinition = validateAndReturnNodeFilterDefinition(componentInstanceId,
184             action, constraint, component);
185         boolean wasLocked = false;
186         try {
187             if (shouldLock) {
188                 lockComponent(component.getUniqueId(), component,"Add Node Filter on Component");
189                 wasLocked = true;
190             }
191             final RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition =
192                 new RequirementNodeFilterPropertyDataDefinition();
193             requirementNodeFilterPropertyDataDefinition.setName(propertyName);
194             requirementNodeFilterPropertyDataDefinition.setConstraints(Collections.singletonList(constraint));
195             final Either<CINodeFilterDataDefinition, StorageOperationStatus> result = addNewNodeFilter(componentId,
196                 componentInstanceId, propertyName, nodeFilterConstraintType, nodeFilterDataDefinition,
197                 requirementNodeFilterPropertyDataDefinition);
198             if (result.isRight()) {
199                 janusGraphDao.rollback();
200                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
201                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
202             } else {
203                 nodeFilterDataDefinition = result.left().value();
204             }
205             janusGraphDao.commit();
206             LOGGER.debug("Node filter successfully created in component {} . ", component.getSystemName());
207
208         } catch (final Exception e) {
209             janusGraphDao.rollback();
210             LOGGER.error(BUSINESS_PROCESS_ERROR,
211                 "Exception occurred during add component node filter property values: {}", e.getMessage(), e);
212             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
213
214         } finally {
215             if (wasLocked) {
216                 unlockComponent(component.getUniqueId(), componentTypeEnum);
217             }
218         }
219         return Optional.ofNullable(nodeFilterDataDefinition);
220     }
221
222     public Optional<CINodeFilterDataDefinition> deleteNodeFilter(final String componentId,
223                                                                  final String componentInstanceId,
224                                                                  final NodeFilterConstraintAction action,
225                                                                  final String constraint,
226                                                                  final int position,
227                                                                  final boolean shouldLock,
228                                                                  final ComponentTypeEnum componentTypeEnum)
229         throws BusinessLogicException {
230
231         final Component component = getComponent(componentId);
232         CINodeFilterDataDefinition nodeFilterDataDefinition =
233             validateAndReturnNodeFilterDefinition(componentInstanceId, action, constraint, component);
234         boolean wasLocked = false;
235         try {
236             if (shouldLock) {
237                 lockComponent(component.getUniqueId(), component,"Add Node Filter on Component");
238                 wasLocked = true;
239             }
240             final Either<CINodeFilterDataDefinition, StorageOperationStatus> result = nodeFilterOperation
241                 .deleteConstraint(componentId, componentInstanceId, nodeFilterDataDefinition, position);
242             if (result.isRight()) {
243                 janusGraphDao.rollback();
244                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
245                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
246             } else {
247                 nodeFilterDataDefinition = result.left().value();
248             }
249             janusGraphDao.commit();
250             LOGGER.debug("Node filter successfully deleted in component {} . ", component.getSystemName());
251
252         } catch (final Exception e) {
253             janusGraphDao.rollback();
254             LOGGER.error(BUSINESS_PROCESS_ERROR,
255                 "Exception occurred during delete component node filter property values: {}", e.getMessage(), e);
256             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
257
258         } finally {
259             if (wasLocked) {
260                 unlockComponent(component.getUniqueId(), componentTypeEnum);
261             }
262         }
263         return Optional.ofNullable(nodeFilterDataDefinition);
264     }
265
266     public Optional<CINodeFilterDataDefinition> updateNodeFilter(final String componentId,
267                                                                  final String componentInstanceId,
268                                                                  final List<String> constraints,
269                                                                  final boolean shouldLock,
270                                                                  final ComponentTypeEnum componentTypeEnum)
271         throws BusinessLogicException {
272
273         final Component component = getComponent(componentId);
274
275         final Either<Boolean, ResponseFormat> response = nodeFilterValidator
276             .validateFilter(component, componentInstanceId, constraints, NodeFilterConstraintAction.UPDATE);
277         if (response.isRight()) {
278             throw new BusinessLogicException(componentsUtils
279                 .getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND, response.right().value().getFormattedMessage()));
280         }
281         final Optional<ComponentInstance> componentInstance = getComponentInstance(componentInstanceId,
282             component);
283         if (!componentInstance.isPresent()) {
284             throw new BusinessLogicException(ResponseFormatManager.getInstance()
285                 .getResponseFormat(ActionStatus.GENERAL_ERROR));
286         }
287         CINodeFilterDataDefinition nodeFilterDataDefinition = componentInstance.get().getNodeFilter();
288         if (nodeFilterDataDefinition == null) {
289             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND));
290         }
291         boolean wasLocked = false;
292         try {
293             if (shouldLock) {
294                 lockComponent(component.getUniqueId(), component,"Update Node Filter on Component");
295                 wasLocked = true;
296             }
297             final List<RequirementNodeFilterPropertyDataDefinition> properties = constraints.stream()
298                 .map(this::getRequirementNodeFilterPropertyDataDefinition).collect(Collectors.toList());
299             final Either<CINodeFilterDataDefinition, StorageOperationStatus> result = nodeFilterOperation
300                 .updateProperties(componentId, componentInstanceId, nodeFilterDataDefinition, properties);
301
302             if (result.isRight()) {
303                 janusGraphDao.rollback();
304                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
305                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
306             } else {
307                 nodeFilterDataDefinition = result.left().value();
308             }
309             janusGraphDao.commit();
310             LOGGER.debug("Node filter successfully updated in component {} . ", component.getSystemName());
311
312         } catch (final Exception e) {
313             janusGraphDao.rollback();
314             LOGGER.error(BUSINESS_PROCESS_ERROR,
315                 "Exception occurred during update component node filter property values: {}",
316                 e.getMessage(), e);
317             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
318
319         } finally {
320             if (wasLocked) {
321                 unlockComponent(component.getUniqueId(), componentTypeEnum);
322             }
323         }
324         return Optional.ofNullable(nodeFilterDataDefinition);
325     }
326
327     private Either<CINodeFilterDataDefinition, StorageOperationStatus> addNewNodeFilter(
328         final String componentId,
329         final String componentInstanceId,
330         final String propertyName,
331         final NodeFilterConstraintType nodeFilterConstraintType,
332         final CINodeFilterDataDefinition nodeFilterDataDefinition,
333         final RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition) {
334
335         if (NodeFilterConstraintType.PROPERTIES.equals(nodeFilterConstraintType)) {
336             return nodeFilterOperation.addNewProperty(componentId, componentInstanceId, nodeFilterDataDefinition,
337                 requirementNodeFilterPropertyDataDefinition);
338         }
339         final RequirementNodeFilterCapabilityDataDefinition requirementNodeFilterCapabilityDataDefinition =
340             new RequirementNodeFilterCapabilityDataDefinition();
341         requirementNodeFilterCapabilityDataDefinition.setName(propertyName);
342         final ListDataDefinition<RequirementNodeFilterPropertyDataDefinition>
343             propertyDataDefinitionListDataDefinition = new ListDataDefinition<>();
344         propertyDataDefinitionListDataDefinition.getListToscaDataDefinition().addAll(
345             Collections.singleton(requirementNodeFilterPropertyDataDefinition));
346         requirementNodeFilterCapabilityDataDefinition.setProperties(propertyDataDefinitionListDataDefinition);
347         return nodeFilterOperation.addNewCapabilities(componentId, componentInstanceId, nodeFilterDataDefinition,
348             requirementNodeFilterCapabilityDataDefinition);
349     }
350
351     private void unlockComponent(final String componentUniqueId,
352                                  final ComponentTypeEnum componentType) {
353         graphLockOperation.unlockComponent(componentUniqueId, componentType.getNodeType());
354     }
355
356     public User validateUser(final String userId) {
357         final User user = userValidations.validateUserExists(userId);
358         userValidations.validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN));
359         return user;
360     }
361
362     private Optional<ComponentInstance> getComponentInstance(final String componentInstanceId,
363                                                              final Component component) {
364         return component.getComponentInstanceById(componentInstanceId);
365     }
366
367     private Optional<CINodeFilterDataDefinition> getCiNodeFilterDataDefinition(
368         final Optional<ComponentInstance> componentInstance) {
369
370         if (componentInstance.isPresent()) {
371             return Optional.ofNullable(componentInstance.get().getNodeFilter());
372         }
373         return Optional.empty();
374     }
375
376     private Optional<CINodeFilterDataDefinition> getCiNodeFilterDataDefinition(final String componentInstanceId,
377                                                                                final Component component)
378         throws BusinessLogicException {
379
380         final Either<Boolean, ResponseFormat> response = nodeFilterValidator
381             .validateComponentInstanceExist(component, componentInstanceId);
382         if (response.isRight()) {
383             throw new BusinessLogicException(componentsUtils
384                 .getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND, response.right().value().getFormattedMessage()));
385         }
386         final Optional<ComponentInstance> componentInstance = getComponentInstance(componentInstanceId, component);
387         if (componentInstance.isPresent()) {
388             return Optional.ofNullable(componentInstance.get().getNodeFilter());
389         }
390         return Optional.empty();
391     }
392
393     private RequirementNodeFilterPropertyDataDefinition getRequirementNodeFilterPropertyDataDefinition(
394         final String constraint) {
395
396         final RequirementNodeFilterPropertyDataDefinition pdd = new RequirementNodeFilterPropertyDataDefinition();
397         pdd.setConstraints(Arrays.asList(constraint));
398         return pdd;
399     }
400
401     private CINodeFilterDataDefinition validateAndReturnNodeFilterDefinition(final String componentInstanceId,
402                                                                              final NodeFilterConstraintAction action,
403                                                                              final String constraint,
404                                                                              final Component component)
405         throws BusinessLogicException {
406
407         validateNodeFilter(component, componentInstanceId, action, constraint);
408         final Optional<CINodeFilterDataDefinition> cINodeFilterDataDefinition = getCiNodeFilterDataDefinition(
409             componentInstanceId, component);
410         if (!cINodeFilterDataDefinition.isPresent()) {
411             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND));
412         }
413         return cINodeFilterDataDefinition.get();
414     }
415
416     private void validateNodeFilter(final Component component,
417                                     final String componentInstanceId,
418                                     final NodeFilterConstraintAction action,
419                                     final String constraint) throws BusinessLogicException {
420         final Either<Boolean, ResponseFormat> response = nodeFilterValidator
421             .validateFilter(component, componentInstanceId, Collections.singletonList(constraint), action);
422         if (response.isRight()) {
423             throw new BusinessLogicException(componentsUtils
424                 .getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND, response.right().value().getFormattedMessage()));
425         }
426     }
427 }