eb8b35ec605b148df350f6933400ce419d1aa21d
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ComponentInterfaceOperationBusinessLogic.java
1 /*
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  *  Copyright (C) 2021 Nordix Foundation. All rights reserved.
6  *  ================================================================================
7  *  Licensed under the Apache License, Version 2.0 (the "License");
8  *  you may not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.zone-instance.component.ts
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21 package org.openecomp.sdc.be.components.impl;
22
23 import fj.data.Either;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Optional;
29 import java.util.UUID;
30 import org.apache.commons.collections.CollectionUtils;
31 import org.apache.commons.collections.MapUtils;
32 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
33 import org.openecomp.sdc.be.components.validation.ComponentValidations;
34 import org.openecomp.sdc.be.dao.api.ActionStatus;
35 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
36 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
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.ComponentInstanceInterface;
41 import org.openecomp.sdc.be.model.ComponentParametersView;
42 import org.openecomp.sdc.be.model.InterfaceDefinition;
43 import org.openecomp.sdc.be.model.User;
44 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
45 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
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.datastructure.Wrapper;
54 import org.openecomp.sdc.exception.ResponseFormat;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57 import org.springframework.beans.factory.annotation.Autowired;
58
59 @org.springframework.stereotype.Component("componentInterfaceOperationBusinessLogic")
60 public class ComponentInterfaceOperationBusinessLogic extends BaseBusinessLogic {
61
62     private static final Logger LOGGER = LoggerFactory.getLogger(ComponentInterfaceOperationBusinessLogic.class);
63     private final ComponentValidations componentValidations;
64
65     @Autowired
66     public ComponentInterfaceOperationBusinessLogic(final IElementOperation elementDao, final IGroupOperation groupOperation,
67                                                     final IGroupInstanceOperation groupInstanceOperation,
68                                                     final IGroupTypeOperation groupTypeOperation, final InterfaceOperation interfaceOperation,
69                                                     final InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
70                                                     final ArtifactsOperations artifactToscaOperation,
71                                                     final ComponentValidations componentValidations) {
72         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
73             artifactToscaOperation);
74         this.componentValidations = componentValidations;
75     }
76
77     public Optional<ComponentInstance> updateComponentInstanceInterfaceOperation(final String componentId, final String componentInstanceId,
78                                                                                  final InterfaceDefinition interfaceDefinition,
79                                                                                  final ComponentTypeEnum componentTypeEnum,
80                                                                                  final Wrapper<ResponseFormat> errorWrapper, final boolean shouldLock)
81         throws BusinessLogicException {
82         final Component component = getComponent(componentId);
83         final Optional<ComponentInstance> componentInstanceOptional = componentValidations.getComponentInstance(component, componentInstanceId);
84         ResponseFormat responseFormat;
85         if (componentInstanceOptional.isEmpty()) {
86             responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND);
87             LOGGER.debug("Failed to found component instance with id {}, error: {}", componentInstanceId, responseFormat);
88             errorWrapper.setInnerElement(responseFormat);
89             return Optional.empty();
90         }
91         Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaceMap = component.getComponentInstancesInterfaces();
92         if (MapUtils.isEmpty(componentInstancesInterfaceMap)) {
93             componentInstancesInterfaceMap = new HashMap<>();
94             component.setComponentInstancesInterfaces(componentInstancesInterfaceMap);
95         }
96         final List<ComponentInstanceInterface> componentInstanceInterfaceList = componentInstancesInterfaceMap.get(componentInstanceId);
97         if (CollectionUtils.isEmpty(componentInstanceInterfaceList)) {
98             responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND);
99             LOGGER.debug("Failed to found component instance with id {}, error: {}", componentInstanceId, responseFormat);
100             errorWrapper.setInnerElement(responseFormat);
101             return Optional.empty();
102         }
103         final Optional<OperationDataDefinition> optionalOperationDataDefinition = interfaceDefinition.getOperations().values().stream().findFirst();
104         if (optionalOperationDataDefinition.isEmpty()) {
105             responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND);
106             LOGGER.debug("Failed to found interface operation on component instance with id {}, error: {}", componentInstanceId, responseFormat);
107             errorWrapper.setInnerElement(responseFormat);
108             return Optional.empty();
109         }
110         final OperationDataDefinition updatedOperationDataDefinition = optionalOperationDataDefinition.get();
111         final Optional<ComponentInstanceInterface> optionalComponentInstanceInterface = componentInstanceInterfaceList.stream().filter(
112                 ci -> ci.getOperations().values().stream().anyMatch(
113                     operationDataDefinition -> operationDataDefinition.getUniqueId().equalsIgnoreCase(updatedOperationDataDefinition.getUniqueId())))
114             .findFirst();
115         if (optionalComponentInstanceInterface.isEmpty()) {
116             responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT);
117             LOGGER
118                 .debug("Failed to found ComponentInstanceInterface on component instance with id {}, error: {}", componentInstanceId, responseFormat);
119             errorWrapper.setInnerElement(responseFormat);
120             return Optional.empty();
121         }
122         updateOperationDefinitionImplementation(updatedOperationDataDefinition);
123         optionalComponentInstanceInterface.get().getOperations().replace(updatedOperationDataDefinition.getName(), updatedOperationDataDefinition);
124         boolean wasLocked = false;
125         try {
126             if (shouldLock) {
127                 lockComponent(componentId, component, "Update Interface Operation on Component instance");
128                 wasLocked = true;
129             }
130             final StorageOperationStatus status = toscaOperationFacade.updateComponentInstanceInterfaces(component, componentInstanceId);
131             if (status != StorageOperationStatus.OK) {
132                 janusGraphDao.rollback();
133                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
134                 LOGGER.error("Exception occurred when updating Component Instance Interfaces {}", responseFormat);
135                 errorWrapper.setInnerElement(responseFormat);
136                 return Optional.empty();
137             }
138             final ComponentParametersView componentFilter = new ComponentParametersView();
139             componentFilter.disableAll();
140             componentFilter.setIgnoreUsers(false);
141             componentFilter.setIgnoreComponentInstances(false);
142             componentFilter.setIgnoreInterfaces(false);
143             componentFilter.setIgnoreComponentInstancesInterfaces(false);
144             final Either<Component, StorageOperationStatus> operationStatusEither = toscaOperationFacade
145                 .updateComponentInstanceMetadataOfTopologyTemplate(component, componentFilter);
146             if (operationStatusEither.isRight()) {
147                 janusGraphDao.rollback();
148                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
149                 LOGGER.error("Exception occurred when updating Component Instance Topology template {}", responseFormat);
150                 errorWrapper.setInnerElement(responseFormat);
151                 return Optional.empty();
152             }
153             janusGraphDao.commit();
154         } catch (final Exception e) {
155             janusGraphDao.rollback();
156             LOGGER.error("Exception occurred when updating Interface Operation on Component Instance: {}", e.getMessage(), e);
157             responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
158             errorWrapper.setInnerElement(responseFormat);
159             throw new BusinessLogicException(responseFormat);
160         } finally {
161             if (wasLocked) {
162                 unlockComponent(component.getUniqueId(), componentTypeEnum);
163             }
164         }
165         return componentInstanceOptional;
166     }
167
168     public Optional<Component> updateResourceInterfaceOperation(final String componentId,
169                                                                 final String user,
170                                                                 final InterfaceDefinition interfaceDefinition,
171                                                                 final ComponentTypeEnum componentTypeEnum,
172                                                                 final Wrapper<ResponseFormat> errorWrapper,
173                                                                 final boolean shouldLock) throws BusinessLogicException {
174         final var component = getComponent(componentId);
175         validateCanWorkOnComponent(component, user);
176         ResponseFormat responseFormat;
177
178         Map<String, InterfaceDefinition> componentInterfaceMap = component.getInterfaces();
179         final String interfaceDefinitionType = interfaceDefinition.getType();
180         if (MapUtils.isEmpty(componentInterfaceMap)) {
181             componentInterfaceMap = new HashMap<>();
182             componentInterfaceMap.put(interfaceDefinitionType, interfaceDefinition);
183             component.setInterfaces(componentInterfaceMap);
184         } else {
185             InterfaceDefinition componentInterfaceDefinition = componentInterfaceMap.get(interfaceDefinitionType);
186             if (componentInterfaceDefinition == null) {
187                 componentInterfaceDefinition = interfaceDefinition;
188                 componentInterfaceMap.put(interfaceDefinitionType, interfaceDefinition);
189             }
190
191             final Map<String, OperationDataDefinition> interfaceDefinitionOperations = interfaceDefinition.getOperations();
192             final Optional<OperationDataDefinition> optionalOperationDataDefinition = interfaceDefinitionOperations.values().stream().findFirst();
193             if (optionalOperationDataDefinition.isEmpty()) {
194                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND);
195                 LOGGER.debug("Failed to found interface operation on provided InterfaceDefinition {}, error: {}",
196                     interfaceDefinitionType, responseFormat);
197                 errorWrapper.setInnerElement(responseFormat);
198                 return Optional.empty();
199             }
200             final var updatedOperationDataDefinition = optionalOperationDataDefinition.get();
201             updateOperationDefinitionImplementation(updatedOperationDataDefinition);
202             Map<String, OperationDataDefinition> componentOperationDataDefinitionMap = componentInterfaceDefinition.getOperations();
203             if (MapUtils.isEmpty(componentOperationDataDefinitionMap)) {
204                 componentOperationDataDefinitionMap = new HashMap<>();
205                 componentInterfaceDefinition.setOperations(componentOperationDataDefinitionMap);
206             }
207             componentOperationDataDefinitionMap.replace(updatedOperationDataDefinition.getName(), updatedOperationDataDefinition);
208         }
209         boolean wasLocked = false;
210         try {
211             if (shouldLock) {
212                 lockComponent(componentId, component, "Update Interface Operation on Component instance");
213                 wasLocked = true;
214             }
215             final StorageOperationStatus status = toscaOperationFacade.updateComponentInterfaces(component, interfaceDefinitionType);
216             if (status != StorageOperationStatus.OK) {
217                 janusGraphDao.rollback();
218                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
219                 LOGGER.error("Exception occurred when updating Component Instance Interfaces {}", responseFormat);
220                 errorWrapper.setInnerElement(responseFormat);
221                 return Optional.empty();
222             }
223             janusGraphDao.commit();
224         } catch (final Exception e) {
225             janusGraphDao.rollback();
226             LOGGER.error("Exception occurred when updating Interface Operation on Component Instance: ", e);
227             responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
228             errorWrapper.setInnerElement(responseFormat);
229             throw new BusinessLogicException(responseFormat);
230         } finally {
231             if (wasLocked) {
232                 unlockComponent(component.getUniqueId(), componentTypeEnum);
233             }
234         }
235         return Optional.of(component);
236     }
237
238     public Optional<Component> createInterfaceOperationInResource(final String componentId, final InterfaceDefinition interfaceDefinition,
239                                                                   final ComponentTypeEnum componentTypeEnum,
240                                                                   final Wrapper<ResponseFormat> errorWrapper, final boolean shouldLock)
241         throws BusinessLogicException {
242         final Component component = getComponent(componentId);
243         ResponseFormat responseFormat;
244         final String componentInterfaceUpdatedKey = interfaceDefinition.getType();
245
246         Map<String, InterfaceDefinition> componentInterfaceMap = component.getInterfaces();
247         if (MapUtils.isEmpty(componentInterfaceMap)) {
248             componentInterfaceMap = new HashMap<>();
249             component.setInterfaces(componentInterfaceMap);
250         }
251
252         interfaceDefinition.setUniqueId(componentInterfaceUpdatedKey);
253         interfaceDefinition.setToscaResourceName(componentInterfaceUpdatedKey);
254         interfaceDefinition.setUserCreated(true);
255
256         final Optional<OperationDataDefinition> optionalOperationDataDefinition = interfaceDefinition.getOperations().values().stream().findFirst();
257         if (optionalOperationDataDefinition.isEmpty()) {
258             responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND);
259             LOGGER.debug("Failed to found interface operation on component instance with id {}, error: {}", componentId, responseFormat);
260             errorWrapper.setInnerElement(responseFormat);
261             return Optional.empty();
262         }
263
264         final OperationDataDefinition updatedOperationDataDefinition = optionalOperationDataDefinition.get();
265         updatedOperationDataDefinition.setUniqueId(UUID.randomUUID().toString());
266
267         final InterfaceDefinition interfaceDefinitionFound = componentInterfaceMap.get(componentInterfaceUpdatedKey);
268         if (interfaceDefinitionFound != null) {
269             final Map<String, OperationDataDefinition> operationsFromComponent = interfaceDefinitionFound.getOperations();
270             final String updatedOperationDataDefinitionName = updatedOperationDataDefinition.getName();
271             final boolean find = operationsFromComponent.containsKey(updatedOperationDataDefinitionName);
272             if (find) {
273                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE,
274                     updatedOperationDataDefinitionName);
275                 LOGGER.error("Operation '{}' for Interface '{}' already exist, error: '{}'", updatedOperationDataDefinitionName,
276                     componentInterfaceUpdatedKey, responseFormat);
277                 errorWrapper.setInnerElement(responseFormat);
278                 return Optional.empty();
279             } else {
280                 operationsFromComponent.put(updatedOperationDataDefinitionName, updatedOperationDataDefinition);
281                 interfaceDefinition.setOperations(operationsFromComponent);
282             }
283         }
284
285         componentInterfaceMap.put(componentInterfaceUpdatedKey, interfaceDefinition);
286
287         boolean wasLocked = false;
288         try {
289             if (shouldLock) {
290                 lockComponent(componentId, component, "Update Interface Operation on Component instance");
291                 wasLocked = true;
292             }
293             final Either<InterfaceDefinition, StorageOperationStatus> operationStatusEither =
294                 toscaOperationFacade.addInterfaceToComponent(componentInterfaceUpdatedKey, interfaceDefinition, component);
295             if (operationStatusEither.isRight()) {
296                 janusGraphDao.rollback();
297                 responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
298                 LOGGER.error("Exception occurred when updating Component Instance Interfaces {}", responseFormat);
299                 errorWrapper.setInnerElement(responseFormat);
300                 return Optional.empty();
301             }
302             janusGraphDao.commit();
303         } catch (final Exception e) {
304             janusGraphDao.rollback();
305             LOGGER.error("Exception occurred when updating Interface Operation on Component Instance: ", e);
306             responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
307             errorWrapper.setInnerElement(responseFormat);
308             throw new BusinessLogicException(responseFormat);
309         } finally {
310             if (wasLocked) {
311                 unlockComponent(component.getUniqueId(), componentTypeEnum);
312             }
313         }
314         return Optional.of(component);
315     }
316
317     public User validateUser(final String userId) {
318         final User user = userValidations.validateUserExists(userId);
319         userValidations.validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN));
320         return user;
321     }
322
323     private void unlockComponent(final String componentUniqueId, final ComponentTypeEnum componentType) {
324         graphLockOperation.unlockComponent(componentUniqueId, componentType.getNodeType());
325     }
326
327     private void updateOperationDefinitionImplementation(final OperationDataDefinition updatedOperationDataDefinition) {
328         final ArtifactDataDefinition artifactInfo = new ArtifactDataDefinition(updatedOperationDataDefinition.getImplementation());
329         artifactInfo.setArtifactName(String.format("'%s'", updatedOperationDataDefinition.getImplementation().getArtifactName()));
330         updatedOperationDataDefinition.setImplementation(artifactInfo);
331     }
332 }