55c70ed2714404cd538a6fefb05989988a8a10da
[sdc.git] /
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.be.dao.api.ActionStatus.SUBSTITUTION_FILTER_NOT_FOUND;
23 import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR;
24
25 import fj.data.Either;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.Optional;
30 import java.util.stream.Collectors;
31 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
32 import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction;
33 import org.openecomp.sdc.be.components.validation.NodeFilterValidator;
34 import org.openecomp.sdc.be.dao.api.ActionStatus;
35 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
36 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
37 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
38 import org.openecomp.sdc.be.model.Component;
39 import org.openecomp.sdc.be.model.ComponentInstance;
40 import org.openecomp.sdc.be.model.User;
41 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
42 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
43 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.SubstitutionFilterOperation;
44 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
45 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
46 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
47 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
48 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
49 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
50 import org.openecomp.sdc.be.user.Role;
51 import org.openecomp.sdc.common.log.wrappers.Logger;
52 import org.openecomp.sdc.exception.ResponseFormat;
53 import org.springframework.beans.factory.annotation.Autowired;
54
55 @org.springframework.stereotype.Component("componentSubstitutionFilterBusinessLogic")
56 public class ComponentSubstitutionFilterBusinessLogic extends BaseBusinessLogic {
57
58     private static final Logger LOGGER = Logger.getLogger(ComponentSubstitutionFilterBusinessLogic.class);
59
60     private final SubstitutionFilterOperation substitutionFilterOperation;
61     private final NodeFilterValidator nodeFilterValidator;
62
63     @Autowired
64     public ComponentSubstitutionFilterBusinessLogic(final IElementOperation elementDao,
65                                                     final IGroupOperation groupOperation,
66                                                     final IGroupInstanceOperation groupInstanceOperation,
67                                                     final IGroupTypeOperation groupTypeOperation,
68                                                     final InterfaceOperation interfaceOperation,
69                                                     final InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
70                                                     final ArtifactsOperations artifactToscaOperation,
71                                                     final SubstitutionFilterOperation substitutionFilterOperation,
72                                                     final NodeFilterValidator nodeFilterValidator) {
73         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation,
74             interfaceLifecycleTypeOperation, artifactToscaOperation);
75         this.substitutionFilterOperation = substitutionFilterOperation;
76         this.nodeFilterValidator = nodeFilterValidator;
77     }
78
79     public Optional<SubstitutionFilterDataDefinition> createSubstitutionFilterIfNotExist(final String componentId,
80                                                                                          final String componentInstanceId,
81                                                                                          final boolean shouldLock,
82                                                                                          final ComponentTypeEnum componentTypeEnum)
83         throws BusinessLogicException {
84
85         final Component component = getComponent(componentId);
86         final Optional<ComponentInstance> componentInstanceOptional =
87             getComponentInstance(componentInstanceId, component);
88
89         Optional<SubstitutionFilterDataDefinition> substitutionFilterDataDefinition;
90         if (componentInstanceOptional.isPresent()) {
91             substitutionFilterDataDefinition = getSubstitutionFilterDataDefinition(componentInstanceOptional.get());
92             if (substitutionFilterDataDefinition.isPresent()) {
93                 return substitutionFilterDataDefinition;
94             }
95         }
96         boolean wasLocked = false;
97         try {
98             if (shouldLock) {
99                 lockComponent(component.getUniqueId(), component, "Create Substitution Filter on component");
100                 wasLocked = true;
101             }
102             final Either<SubstitutionFilterDataDefinition, StorageOperationStatus> result = substitutionFilterOperation
103                 .createSubstitutionFilter(componentId, componentInstanceId);
104             if (result.isRight()) {
105                 janusGraphDao.rollback();
106                 LOGGER.error(BUSINESS_PROCESS_ERROR,
107                     "Failed to Create Substitution filter on component with id {}", componentId);
108                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
109                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
110             }
111             substitutionFilterDataDefinition = Optional.ofNullable(result.left().value());
112             if (componentInstanceOptional.isPresent() && substitutionFilterDataDefinition.isPresent()) {
113                 componentInstanceOptional.get().setSubstitutionFilter(substitutionFilterDataDefinition.get());
114             }
115             janusGraphDao.commit();
116             LOGGER.debug("Substitution filter successfully created in component {} . ", component.getSystemName());
117         } catch (final Exception e) {
118             janusGraphDao.rollback();
119             LOGGER.error(BUSINESS_PROCESS_ERROR,
120                 "Exception occurred during add Component Substitution filter property values: {}", e.getMessage(), e);
121             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
122
123         } finally {
124             if (wasLocked) {
125                 unlockComponent(component.getUniqueId(), componentTypeEnum);
126             }
127         }
128
129         return substitutionFilterDataDefinition;
130     }
131
132     public Optional<SubstitutionFilterDataDefinition> addSubstitutionFilter(final String componentId,
133                                                                             final String componentInstanceId,
134                                                                             final NodeFilterConstraintAction action,
135                                                                             final String propertyName,
136                                                                             final String constraint,
137                                                                             final boolean shouldLock,
138                                                                             final ComponentTypeEnum componentTypeEnum)
139         throws BusinessLogicException {
140
141         final Component component = getComponent(componentId);
142         SubstitutionFilterDataDefinition substitutionFilterDataDefinition = validateAndReturnSubstitutionFilterDefinition(
143             componentInstanceId,
144             action, constraint, component);
145         boolean wasLocked = false;
146         try {
147             if (shouldLock) {
148                 lockComponent(component.getUniqueId(), component, "Add Substitution Filter on Component");
149                 wasLocked = true;
150             }
151             final RequirementSubstitutionFilterPropertyDataDefinition newProperty =
152                 new RequirementSubstitutionFilterPropertyDataDefinition();
153             newProperty.setName(propertyName);
154             newProperty.setConstraints(Collections.singletonList(constraint));
155             final Either<SubstitutionFilterDataDefinition, StorageOperationStatus> result = substitutionFilterOperation
156                 .addNewProperty(componentId, componentInstanceId, substitutionFilterDataDefinition, newProperty);
157
158             if (result.isRight()) {
159                 janusGraphDao.rollback();
160                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
161                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
162             } else {
163                 substitutionFilterDataDefinition = result.left().value();
164             }
165             janusGraphDao.commit();
166             LOGGER.debug("Substitution filter successfully created in component {} . ", component.getSystemName());
167
168         } catch (final Exception e) {
169             janusGraphDao.rollback();
170             LOGGER.error(BUSINESS_PROCESS_ERROR,
171                 "Exception occurred during add component substitution filter property values: {}", e.getMessage(), e);
172             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
173
174         } finally {
175             if (wasLocked) {
176                 unlockComponent(component.getUniqueId(), componentTypeEnum);
177             }
178         }
179         return Optional.ofNullable(substitutionFilterDataDefinition);
180     }
181
182     public Optional<SubstitutionFilterDataDefinition> updateSubstitutionFilter(final String componentId,
183                                                                                final String componentInstanceId,
184                                                                                final List<String> constraints,
185                                                                                final boolean shouldLock,
186                                                                                final ComponentTypeEnum componentTypeEnum)
187         throws BusinessLogicException {
188
189         final Component component = getComponent(componentId);
190
191         final Either<Boolean, ResponseFormat> response = nodeFilterValidator
192             .validateFilter(component, componentInstanceId, constraints, NodeFilterConstraintAction.UPDATE);
193         if (response.isRight()) {
194             throw new BusinessLogicException(componentsUtils
195                 .getResponseFormat(SUBSTITUTION_FILTER_NOT_FOUND, response.right().value().getFormattedMessage()));
196         }
197         final Optional<ComponentInstance> componentInstance = getComponentInstance(componentInstanceId,
198             component);
199         if (!componentInstance.isPresent()) {
200             throw new BusinessLogicException(ResponseFormatManager.getInstance()
201                 .getResponseFormat(ActionStatus.GENERAL_ERROR));
202         }
203         SubstitutionFilterDataDefinition substitutionFilterDataDefinition = componentInstance.get()
204             .getSubstitutionFilter();
205         if (substitutionFilterDataDefinition == null) {
206             throw new BusinessLogicException(componentsUtils.getResponseFormat(SUBSTITUTION_FILTER_NOT_FOUND));
207         }
208         boolean wasLocked = false;
209         try {
210             if (shouldLock) {
211                 lockComponent(component.getUniqueId(), component, "Update Substitution Filter on Component");
212                 wasLocked = true;
213             }
214             final List<RequirementSubstitutionFilterPropertyDataDefinition> properties = constraints.stream()
215                 .map(this::getRequirementSubstitutionFilterPropertyDataDefinition).collect(Collectors.toList());
216             final Either<SubstitutionFilterDataDefinition, StorageOperationStatus> result = substitutionFilterOperation
217                 .updateSubstitutionFilter(componentId, componentInstanceId, substitutionFilterDataDefinition, properties);
218
219             if (result.isRight()) {
220                 janusGraphDao.rollback();
221                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
222                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
223             } else {
224                 substitutionFilterDataDefinition = result.left().value();
225             }
226             janusGraphDao.commit();
227             LOGGER.debug("Substitution filter successfully updated in component {} . ", component.getSystemName());
228
229         } catch (final Exception e) {
230             janusGraphDao.rollback();
231             LOGGER.error(BUSINESS_PROCESS_ERROR, this.getClass().getName(),
232                 "Exception occurred during update component substitution filter property values: {}", e);
233             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
234
235         } finally {
236             if (wasLocked) {
237                 unlockComponent(component.getUniqueId(), componentTypeEnum);
238             }
239         }
240         return Optional.ofNullable(substitutionFilterDataDefinition);
241     }
242
243     public Optional<SubstitutionFilterDataDefinition> deleteSubstitutionFilter(final String componentId,
244                                                                                final String componentInstanceId,
245                                                                                final NodeFilterConstraintAction action,
246                                                                                final String constraint,
247                                                                                final int position,
248                                                                                final boolean shouldLock,
249                                                                                final ComponentTypeEnum componentTypeEnum)
250         throws BusinessLogicException {
251
252         final Component component = getComponent(componentId);
253         SubstitutionFilterDataDefinition substitutionFilterDataDefinition =
254             validateAndReturnSubstitutionFilterDefinition(componentInstanceId, action, constraint, component);
255         boolean wasLocked = false;
256         try {
257             if (shouldLock) {
258                 lockComponent(component.getUniqueId(), component,"Add Node Filter on Component");
259                 wasLocked = true;
260             }
261             final Either<SubstitutionFilterDataDefinition, StorageOperationStatus> result = substitutionFilterOperation
262                 .deleteConstraint(componentId, componentInstanceId, substitutionFilterDataDefinition, position);
263             if (result.isRight()) {
264                 janusGraphDao.rollback();
265                 throw new BusinessLogicException(componentsUtils.getResponseFormatByResource(componentsUtils
266                     .convertFromStorageResponse(result.right().value()), component.getSystemName()));
267             } else {
268                 substitutionFilterDataDefinition = result.left().value();
269             }
270             janusGraphDao.commit();
271             LOGGER.debug("Substitution filter successfully deleted in component {} . ", component.getSystemName());
272
273         } catch (final Exception e) {
274             janusGraphDao.rollback();
275             LOGGER.error(BUSINESS_PROCESS_ERROR,
276                 "Exception occurred during delete component substitution filter property values: {}",
277                 e.getMessage(), e);
278             throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
279
280         } finally {
281             if (wasLocked) {
282                 unlockComponent(component.getUniqueId(), componentTypeEnum);
283             }
284         }
285         return Optional.ofNullable(substitutionFilterDataDefinition);
286     }
287
288     private Optional<SubstitutionFilterDataDefinition> getSubstitutionFilterDataDefinition(
289         final ComponentInstance componentInstance) {
290
291         final SubstitutionFilterDataDefinition substitutionFilterDataDefinition =
292             componentInstance.getSubstitutionFilter();
293         if (componentInstance.getSubstitutionFilter() != null) {
294             return Optional.ofNullable(substitutionFilterDataDefinition);
295         }
296         return Optional.empty();
297     }
298
299     private void unlockComponent(final String componentUniqueId,
300                                  final ComponentTypeEnum componentType) {
301         graphLockOperation.unlockComponent(componentUniqueId, componentType.getNodeType());
302     }
303
304     public User validateUser(final String userId) {
305         final User user = userValidations.validateUserExists(userId);
306         userValidations.validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN));
307         return user;
308     }
309
310     private Optional<ComponentInstance> getComponentInstance(final String componentInstanceId,
311                                                              final Component component) {
312         return component.getComponentInstanceById(componentInstanceId);
313     }
314
315     private Optional<SubstitutionFilterDataDefinition> getComponentInstanceSubstitutionFilterDataDefinition(
316         final String componentInstanceId, final Component component)
317         throws BusinessLogicException {
318
319         if (nodeFilterValidator.validateComponentInstanceExist(component, componentInstanceId).isRight()) {
320             throw new BusinessLogicException(componentsUtils
321                 .getResponseFormat(SUBSTITUTION_FILTER_NOT_FOUND));
322         }
323         return getComponentInstance(componentInstanceId, component).map(ComponentInstance::getSubstitutionFilter);
324     }
325
326     private SubstitutionFilterDataDefinition validateAndReturnSubstitutionFilterDefinition(
327         final String componentInstanceId, final NodeFilterConstraintAction action, final String constraint,
328         final Component component) throws BusinessLogicException {
329
330         validateSubstitutionFilter(component, componentInstanceId, action, constraint);
331         final Optional<SubstitutionFilterDataDefinition> substitutionFilterDataDefinition =
332             getComponentInstanceSubstitutionFilterDataDefinition(componentInstanceId, component);
333         if (!substitutionFilterDataDefinition.isPresent()) {
334             throw new BusinessLogicException(componentsUtils.getResponseFormat(SUBSTITUTION_FILTER_NOT_FOUND));
335         }
336         return substitutionFilterDataDefinition.get();
337     }
338
339     private void validateSubstitutionFilter(final Component component,
340                                             final String componentInstanceId,
341                                             final NodeFilterConstraintAction action,
342                                             final String constraint) throws BusinessLogicException {
343         final Either<Boolean, ResponseFormat> response = nodeFilterValidator
344             .validateFilter(component, componentInstanceId, Collections.singletonList(constraint), action);
345         if (response.isRight()) {
346             throw new BusinessLogicException(componentsUtils
347                 .getResponseFormat(SUBSTITUTION_FILTER_NOT_FOUND, response.right().value().getFormattedMessage()));
348         }
349     }
350
351     private RequirementSubstitutionFilterPropertyDataDefinition getRequirementSubstitutionFilterPropertyDataDefinition(
352         final String constraint) {
353
354         final RequirementSubstitutionFilterPropertyDataDefinition requirementSubstitutionFilterPropertyDataDefinition =
355             new RequirementSubstitutionFilterPropertyDataDefinition();
356         requirementSubstitutionFilterPropertyDataDefinition.setConstraints(Arrays.asList(constraint));
357         return requirementSubstitutionFilterPropertyDataDefinition;
358     }
359 }