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