c1669d18f6522a8a6526df5432ca29b0203da01e
[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, capabilityName);
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                                                                              final String capabilityName)
296         throws BusinessLogicException {
297         validateNodeFilter(component, componentInstanceId, action, constraint, nodeFilterConstraintType, capabilityName);
298         final Optional<CINodeFilterDataDefinition> cINodeFilterDataDefinition = getCiNodeFilterDataDefinition(componentInstanceId, component);
299         if (!cINodeFilterDataDefinition.isPresent()) {
300             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND));
301         }
302         return cINodeFilterDataDefinition.get();
303     }
304
305     private void validateNodeFilter(final Component component, final String componentInstanceId, final NodeFilterConstraintAction action,
306                                     final String constraint, final NodeFilterConstraintType nodeFilterConstraintType, final String capabilityName) throws BusinessLogicException {
307         final Either<Boolean, ResponseFormat> response = nodeFilterValidator
308             .validateFilter(component, componentInstanceId, Collections.singletonList(constraint), action, nodeFilterConstraintType, capabilityName);
309         if (response.isRight()) {
310             throw new BusinessLogicException(
311                 componentsUtils.getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND, response.right().value().getFormattedMessage()));
312         }
313     }
314
315     public Optional<CINodeFilterDataDefinition> updateNodeFilter(final String componentId, final String componentInstanceId,
316                                                                  final UIConstraint uiConstraint, final ComponentTypeEnum componentTypeEnum,
317                                                                  final NodeFilterConstraintType nodeFilterConstraintType, final int index)
318         throws BusinessLogicException {
319         final Optional<CINodeFilterDataDefinition> deleteActionResponse = deleteNodeFilter(componentId, componentInstanceId,
320             NodeFilterConstraintAction.DELETE, null, index, true, componentTypeEnum, nodeFilterConstraintType);
321         if (!deleteActionResponse.isPresent()) {
322             throw new BusinessLogicException(
323                 componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR, "Failed to delete node filter capabilities"));
324         }
325         return addNodeFilter(componentId.toLowerCase(), componentInstanceId, NodeFilterConstraintAction.ADD, uiConstraint.getServicePropertyName(),
326             new ConstraintConvertor().convert(uiConstraint), true, componentTypeEnum, nodeFilterConstraintType,
327             uiConstraint.getCapabilityName());
328     }
329
330     public StorageOperationStatus associateNodeFilterToComponentInstance(final String componentId,
331                                                                          final Map<String, UploadNodeFilterInfo> instNodeFilter) {
332         for (Entry<String, UploadNodeFilterInfo> filter : instNodeFilter.entrySet()) {
333             String componentInstanceId = filter.getKey();
334             CINodeFilterDataDefinition ciNodeFilterDataDefinition = new CINodeFilterUtils()
335                 .getNodeFilterDataDefinition(filter.getValue(), componentInstanceId);
336             Either<CINodeFilterDataDefinition, StorageOperationStatus> nodeFilter = nodeFilterOperation.createNodeFilter(componentId,
337                 componentInstanceId);
338             if (nodeFilter.isRight()) {
339                 LOGGER.error(BUSINESS_PROCESS_ERROR, "Failed to Create Node filter on component instance with id {}",
340                     filter.getKey());
341                 return nodeFilter.right().value();
342             }
343
344             //associate node filter properties to component instance
345             List<RequirementNodeFilterPropertyDataDefinition> properties = ciNodeFilterDataDefinition.getProperties()
346                 .getListToscaDataDefinition();
347             if (!properties.isEmpty()) {
348                 properties.forEach(property -> {
349                     RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition =
350                         getRequirementNodeFilterPropertyDataDefinition(property);
351                     Either<CINodeFilterDataDefinition, StorageOperationStatus> nodeFilterProperty = nodeFilterOperation
352                         .addNewProperty(componentId, componentInstanceId, nodeFilter.left().value(), requirementNodeFilterPropertyDataDefinition);
353                     if (nodeFilterProperty.isRight()) {
354                         throw new ComponentException(
355                             componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(nodeFilterProperty.right().value()),
356                                 componentInstanceId));
357                     }
358                 });
359             }
360
361             //associate node filter capabilities to component instance
362             List<RequirementNodeFilterCapabilityDataDefinition> capabilities = ciNodeFilterDataDefinition.getCapabilities()
363                 .getListToscaDataDefinition();
364             if (!capabilities.isEmpty()) {
365                 capabilities.forEach(capability -> {
366                     RequirementNodeFilterCapabilityDataDefinition requirementNodeFilterCapabilityDataDefinition =
367                         new RequirementNodeFilterCapabilityDataDefinition();
368                     requirementNodeFilterCapabilityDataDefinition.setName(capability.getName());
369                     requirementNodeFilterCapabilityDataDefinition.setProperties(getProperties(capability.getProperties()));
370                     Either<CINodeFilterDataDefinition, StorageOperationStatus> nodeFilterCapability = nodeFilterOperation
371                         .addNewCapabilities(componentId, componentInstanceId, nodeFilter.left().value(),
372                             requirementNodeFilterCapabilityDataDefinition);
373                     if (nodeFilterCapability.isRight()) {
374                         throw new ComponentException(
375                             componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(nodeFilterCapability.right().value()),
376                                 componentInstanceId));
377                     }
378                 });
379             }
380         }
381         return StorageOperationStatus.OK;
382     }
383
384     private List<String> getNodeFilterConstraints(String name, List<String> value) {
385         List<String> constraints = new ArrayList<>();
386         String values = value.get(0).split("\n")[0];
387         constraints.add(name + ": {" + values + "}");
388         return constraints;
389     }
390
391     private ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> getProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties) {
392         ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> updatedProperties = new ListDataDefinition<>();
393         properties.getListToscaDataDefinition().forEach(property -> {
394             RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition = getRequirementNodeFilterPropertyDataDefinition(
395                 property);
396             updatedProperties.add(requirementNodeFilterPropertyDataDefinition);
397         });
398         return updatedProperties;
399     }
400
401     private RequirementNodeFilterPropertyDataDefinition getRequirementNodeFilterPropertyDataDefinition(
402         RequirementNodeFilterPropertyDataDefinition property) {
403         RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition = new RequirementNodeFilterPropertyDataDefinition();
404         requirementNodeFilterPropertyDataDefinition.setName(property.getName());
405         requirementNodeFilterPropertyDataDefinition.setConstraints(getNodeFilterConstraints(property.getName(), property.getConstraints()));
406         return requirementNodeFilterPropertyDataDefinition;
407     }
408 }