Revert "Delete workflow artifact
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / InterfaceOperationBusinessLogic.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
17
18 package org.openecomp.sdc.be.components.impl;
19
20 import com.google.common.collect.Sets;
21 import fj.data.Either;
22 import org.apache.commons.collections.MapUtils;
23 import org.openecomp.sdc.be.components.validation.InterfaceOperationValidation;
24 import org.openecomp.sdc.be.dao.api.ActionStatus;
25 import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter;
26 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
27 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
28 import org.openecomp.sdc.be.model.ArtifactDefinition;
29 import org.openecomp.sdc.be.model.ComponentInstance;
30 import org.openecomp.sdc.be.model.ComponentParametersView;
31 import org.openecomp.sdc.be.model.InterfaceDefinition;
32 import org.openecomp.sdc.be.model.Operation;
33 import org.openecomp.sdc.be.model.Resource;
34 import org.openecomp.sdc.be.model.User;
35 import org.openecomp.sdc.be.model.jsontitan.operations.InterfaceOperation;
36 import org.openecomp.sdc.be.model.jsontitan.utils.InterfaceUtils;
37 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
38 import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
39 import org.openecomp.sdc.be.user.Role;
40 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
41 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
42 import org.openecomp.sdc.exception.ResponseFormat;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.springframework.beans.factory.annotation.Autowired;
46 import org.springframework.stereotype.Component;
47
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.HashMap;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.Optional;
54 import java.util.Set;
55 import java.util.UUID;
56 import java.util.stream.Collectors;
57 import java.util.stream.Stream;
58
59 @Component("interfaceOperationBusinessLogic")
60 public class InterfaceOperationBusinessLogic extends ComponentBusinessLogic{
61     private static final Logger LOGGER = LoggerFactory.getLogger(ResourceBusinessLogic.class);
62     @Autowired
63     private InterfaceOperationValidation interfaceOperationValidation;
64
65     @Autowired
66     private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
67
68     @Autowired
69     private InterfaceOperation interfaceOperation;
70
71     public void setInterfaceOperation(InterfaceOperation interfaceOperation) {
72         this.interfaceOperation = interfaceOperation;
73     }
74
75     public InterfaceOperationValidation getInterfaceOperationValidation() {
76         return interfaceOperationValidation;
77     }
78
79     public void setInterfaceOperationValidation(
80             InterfaceOperationValidation interfaceOperationValidation) {
81         this.interfaceOperationValidation = interfaceOperationValidation;
82     }
83
84
85     public Either<Resource, ResponseFormat> deleteInterfaceOperation(String resourceId, Set<String> interfaceOperationToDelete, User user, boolean lock) {
86         Resource resourceToDelete = initResourceToDeleteWFOp(resourceId, interfaceOperationToDelete);
87         Either<Resource, ResponseFormat> eitherDelete = validateUserAndRole(resourceToDelete, user, "deleteInterfaceOperation");
88         if (eitherDelete != null)
89             return eitherDelete;
90
91         Either<Resource, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(resourceId);
92         if (storageStatus.isRight()) {
93             return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.RESOURCE),""));
94         }
95         Resource resource = storageStatus.left().value();
96         if (lock) {
97             Either<Boolean, ResponseFormat> lockResult = lockComponent(resource.getUniqueId(), resource, "Delete interface Operation on a resource");
98             if (lockResult.isRight()) {
99                 LOGGER.debug("Failed to lock resource {}. Response is {}. ", resource.getName(), lockResult.right().value().getFormattedMessage());
100                 titanDao.rollback();
101                 return Either.right(lockResult.right().value());
102             }
103         }
104
105         try {
106             Optional<InterfaceDefinition> optionalInterface = InterfaceUtils
107                     .getInterfaceDefinitionFromToscaName(resource.getInterfaces().values(), resource.getName());
108             Either<InterfaceDefinition, ResponseFormat> sValue = getInterfaceDefinition(resource, optionalInterface.orElse(null));
109             if (sValue.isRight()) {
110                 return Either.right(sValue.right().value());
111             }
112             InterfaceDefinition interfaceDefinition = sValue.left().value();
113             Either<InterfaceDefinition, ResponseFormat> deleteEither;
114
115             for(String operationToDelete : interfaceOperationToDelete) {
116                 deleteEither = deleteOperationFromInterface(interfaceDefinition, operationToDelete);
117                 if (deleteEither.isRight()){
118                     return Either.right(deleteEither.right().value());
119                 }
120                 interfaceDefinition = deleteEither.left().value();
121             }
122
123             Either<InterfaceDefinition, StorageOperationStatus> interfaceUpdate = interfaceOperation.updateInterface(resource.getUniqueId(), interfaceDefinition);
124             if (interfaceUpdate.isRight()) {
125                 LOGGER.debug("Failed to delete interface operation from resource {}. Response is {}. ", resource.getName(), interfaceUpdate.right().value());
126                 titanDao.rollback();
127                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(interfaceUpdate.right().value(), ComponentTypeEnum.RESOURCE)));
128             }
129
130             InterfaceDefinition interfaceDef = interfaceUpdate.left().value();
131             if(interfaceDef.getOperationsMap().isEmpty()){
132                 Either<Set<String>, StorageOperationStatus> deleteInterface = interfaceOperation.deleteInterface(resource, Sets.newHashSet(interfaceDef.getUniqueId()));
133                 if (deleteInterface.isRight()) {
134                     LOGGER.debug("Failed to delete interface from resource {}. Response is {}. ", resource.getName(), deleteInterface.right().value());
135                     titanDao.rollback();
136                     return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(deleteInterface.right().value(), ComponentTypeEnum.RESOURCE)));
137                 }
138             }
139
140             titanDao.commit();
141
142         } catch (Exception e){
143             LOGGER.error("Exception occurred during delete interface operation : {}", e.getMessage(), e);
144             titanDao.rollback();
145             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
146         } finally {
147             graphLockOperation.unlockComponent(resource.getUniqueId(), NodeTypeEnum.Resource);
148         }
149         return Either.left(resource);
150     }
151
152     public Either<InterfaceDefinition, ResponseFormat> getInterfaceDefinition(Resource resource,
153                                                                               InterfaceDefinition interfaceDef) {
154         if (interfaceDef != null){
155             return Either.left(interfaceDef);
156         } else {
157             InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
158             interfaceDefinition.setToscaResourceName(InterfaceUtils.createInterfaceToscaResourceName(resource.getName()));
159             Either<InterfaceDefinition, StorageOperationStatus> interfaceCreateEither = interfaceOperation
160                     .addInterface(resource.getUniqueId(), interfaceDefinition);
161             if (interfaceCreateEither.isRight()){
162                 StorageOperationStatus sValue = interfaceCreateEither.right().value();
163                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(sValue,
164                         ComponentTypeEnum.RESOURCE), ""));
165
166             }
167             return Either.left(interfaceCreateEither.left().value());
168         }
169     }
170
171     private Either<InterfaceDefinition,ResponseFormat> deleteOperationFromInterface(InterfaceDefinition interfaceDefinition, String operationId){
172         Optional<Map.Entry<String, Operation>> operationToRemove = interfaceDefinition.getOperationsMap().entrySet().stream()
173                 .filter(entry -> entry.getValue().getUniqueId().equals(operationId)).findAny();
174         if (operationToRemove.isPresent()){
175             Map.Entry<String, Operation> stringOperationEntry = operationToRemove.get();
176             Map<String, Operation> tempMap = interfaceDefinition.getOperationsMap();
177             tempMap.remove(stringOperationEntry.getKey());
178             interfaceDefinition.setOperationsMap(tempMap);
179             return Either.left(interfaceDefinition);
180         }
181         LOGGER.debug("Failed to delete interface operation");
182         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND));
183     }
184
185     private Either<InterfaceDefinition,ResponseFormat> addOperationToInterface(InterfaceDefinition interfaceDefinition, Operation interfaceOperation){
186         if(interfaceOperation.getUniqueId() == null)
187             interfaceOperation.setUniqueId(UUID.randomUUID().toString());
188         if (interfaceOperation.getImplementationArtifact() == null){
189             initNewOperation(interfaceOperation);
190         }
191         Map<String, Operation> tempMap = interfaceDefinition.getOperationsMap();
192         tempMap.put(interfaceOperation.getUniqueId(), interfaceOperation);
193         interfaceDefinition.setOperationsMap(tempMap);
194         return Either.left(interfaceDefinition);
195     }
196
197     private Either<InterfaceDefinition,ResponseFormat> updateOperationInInterface(InterfaceDefinition interfaceDefinition, Operation interfaceOperation){
198         Optional<Map.Entry<String, Operation>> operationToUpdate = interfaceDefinition.getOperationsMap().entrySet().stream()
199                 .filter(entry -> entry.getValue().getUniqueId().equals(interfaceOperation.getUniqueId())).findAny();
200         if (operationToUpdate.isPresent()){
201             Operation updatedOperation = updateOperation(operationToUpdate.get().getValue(),interfaceOperation);
202             Map<String, Operation> tempMap = interfaceDefinition.getOperationsMap();
203             tempMap.remove(updatedOperation.getUniqueId());
204             tempMap.put(updatedOperation.getUniqueId(), updatedOperation);
205             interfaceDefinition.setOperationsMap(tempMap);
206             return Either.left(interfaceDefinition);
207         }
208         LOGGER.debug("Failed to update interface operation");
209         return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND));
210     }
211
212     private Operation updateOperation(Operation dbOperation, Operation updatedOperation) {
213         dbOperation.setName(updatedOperation.getName());
214         dbOperation.setDescription(updatedOperation.getDescription());
215         dbOperation.setInputs(updatedOperation.getInputs());
216         return dbOperation;
217     }
218
219     public Either<Resource, ResponseFormat> updateInterfaceOperation(String resourceId, Resource resourceUpdate, User user, boolean lock) {
220         return createOrUpdateInterfaceOperation(resourceId, resourceUpdate, user, true, "updateInterfaceOperation", lock);
221     }
222
223     public Either<Resource, ResponseFormat> createInterfaceOperation(String resourceId, Resource resourceUpdate, User user, boolean lock) {
224         return createOrUpdateInterfaceOperation(resourceId, resourceUpdate, user, false, "createInterfaceOperation", lock);
225     }
226
227     private Either<Resource, ResponseFormat> createOrUpdateInterfaceOperation(String resourceId, Resource resourceUpdate, User user, boolean isUpdate, String errorContext, boolean lock) {
228         Either<Resource, ResponseFormat> eitherCreator = validateUserAndRole(resourceUpdate, user, errorContext);
229         if (eitherCreator != null)
230             return eitherCreator;
231
232         Either<Resource, ResponseFormat> resourceEither = getResourceDetails(resourceId);
233         Resource storedResource = resourceEither.left().value();
234
235         Map<String, Operation> interfaceOperations = InterfaceUtils
236                 .getInterfaceOperationsFromInterfaces(resourceUpdate.getInterfaces(), storedResource);
237         if(MapUtils.isEmpty(interfaceOperations) ) {
238             LOGGER.debug("Failed to fetch interface operations from resource {}, error {}",resourceUpdate.getUniqueId(),
239                     ActionStatus.INTERFACE_OPERATION_NOT_FOUND);
240             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND,
241                     resourceUpdate.getUniqueId()));
242         }
243
244         Either<Boolean, ResponseFormat> interfaceOperationValidationResponseEither = interfaceOperationValidation
245                 .validateInterfaceOperations( interfaceOperations.values(), resourceId, isUpdate);
246
247         if(interfaceOperationValidationResponseEither.isRight()) {
248             return      Either.right(interfaceOperationValidationResponseEither.right().value());
249         }
250
251         Either<Boolean, ResponseFormat> lockResult = null;
252         if (lock) {
253             lockResult = lockComponent(storedResource.getUniqueId(), storedResource,
254                     "Create or Update interface Operation on Resource");
255             if (lockResult.isRight()) {
256                 LOGGER.debug("Failed to lock resource {}. Response is {}. ", storedResource.getName(), lockResult.right().value().getFormattedMessage());
257                 titanDao.rollback();
258                 return Either.right(lockResult.right().value());
259             } else {
260                 LOGGER.debug("The resource with system name {} locked. ", storedResource.getSystemName());
261             }
262         }
263
264         Either<InterfaceDefinition, ResponseFormat> result;
265         Map<String, InterfaceDefinition> resultMap = new HashMap<>();
266
267         try {
268             Optional<InterfaceDefinition> optionalInterface = InterfaceUtils
269                     .getInterfaceDefinitionFromToscaName(storedResource.getInterfaces().values(), storedResource.getName());
270             Either<InterfaceDefinition, ResponseFormat> sValue = getInterfaceDefinition(storedResource, optionalInterface.orElse(null));
271             if (sValue.isRight()) {
272                 return Either.right(sValue.right().value());
273             }
274             InterfaceDefinition interfaceDefinition = sValue.left().value();
275
276             for (Operation interfaceOperation : interfaceOperations.values()) {
277                 if (isUpdate) {
278                     result = updateOperationInInterface(interfaceDefinition, interfaceOperation);
279                 } else {
280                     result = addOperationToInterface(interfaceDefinition, interfaceOperation);
281                 }
282                 if (result.isRight()) {
283                     titanDao.rollback();
284                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
285                 } else {
286                     interfaceDefinition = result.left().value();
287                     resultMap.put(interfaceDefinition.getUniqueId(), interfaceDefinition);
288                 }
289             }
290
291             Either<InterfaceDefinition, StorageOperationStatus> interfaceUpdate = interfaceOperation
292                     .updateInterface(storedResource.getUniqueId(), interfaceDefinition);
293             if (interfaceUpdate.isRight()) {
294                 LOGGER.debug("Failed to add or update interface operation on resource {}. Response is {}. ", storedResource.getName(), interfaceUpdate.right().value());
295                 titanDao.rollback();
296                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(interfaceUpdate.right().value(), ComponentTypeEnum.RESOURCE)));
297             }
298
299             titanDao.commit();
300
301             Resource resource = createVFWithInterfaceOperationForResponse(resourceId, resultMap);
302             return Either.left(resource);
303         }
304         catch (Exception e) {
305             titanDao.rollback();
306             LOGGER.error("Exception occurred during add or update interface operation property values:{}",
307                     e.getMessage(), e);
308             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
309         }
310         finally {
311             if (lockResult != null && lockResult.isLeft() && lockResult.left().value()) {
312                 graphLockOperation.unlockComponent(storedResource.getUniqueId(), NodeTypeEnum.Resource);
313             }
314         }
315     }
316
317     private void initNewOperation(Operation operation){
318         ArtifactDefinition artifactDefinition = new ArtifactDefinition();
319         String artifactUUID = UUID.randomUUID().toString();
320         artifactDefinition.setArtifactUUID(artifactUUID);
321         artifactDefinition.setUniqueId(artifactUUID);
322         artifactDefinition.setArtifactType(ArtifactTypeEnum.PLAN.getType());
323         artifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.LIFE_CYCLE);
324         operation.setImplementation(artifactDefinition);
325     }
326
327     private Resource initResourceToDeleteWFOp(String resourceId, Collection<String> interfaceOperationsToDelete) {
328         InterfaceDefinition id = new InterfaceDefinition();
329         id.setUniqueId(UUID.randomUUID().toString());
330         interfaceOperationsToDelete.forEach(interfaceOpToDelete -> id.getOperationsMap().put(interfaceOpToDelete, new Operation()));
331         Map<String, InterfaceDefinition> interfaceDefinitionMap = new HashMap<>();
332         interfaceDefinitionMap.put(id.getUniqueId(), id);
333
334         Resource resourceToDelete = new Resource();
335         resourceToDelete.setUniqueId(resourceId);
336         resourceToDelete.setInterfaces(interfaceDefinitionMap);
337
338         return resourceToDelete;
339     }
340
341     private Either<Resource, ResponseFormat> validateUserAndRole(Resource resourceUpdate, User user, String errorContext) {
342         Either<User, ResponseFormat> userEither = validateUser(user, errorContext, resourceUpdate, null, false);
343         if (userEither.isRight()) {
344             return Either.right(userEither.right().value());
345         }
346         user = userEither.left().value();
347
348         Either<Boolean, ResponseFormat> userRoleEither = validateUserRole(user, resourceUpdate, new ArrayList<>(), null, null);
349         if (userRoleEither.isRight()) {
350             return Either.right(userRoleEither.right().value());
351         }
352         return null;
353     }
354
355
356
357     private Resource createVFWithInterfaceOperationForResponse(String resourceId, Map<String, InterfaceDefinition> interfaceDefinitionMap) {
358         Resource resource = new Resource();
359         resource.setUniqueId(resourceId);
360         resource.setInterfaces(interfaceDefinitionMap);
361         return resource;
362     }
363
364     public Either<Resource, ResponseFormat> getResourceDetails(String resourceId){
365         Either<Resource, StorageOperationStatus> resourceStorageOperationStatusEither =
366                 toscaOperationFacade.getToscaElement(resourceId);
367         if (resourceStorageOperationStatusEither.isRight()) {
368             StorageOperationStatus errorStatus = resourceStorageOperationStatusEither.right().value();
369             LOGGER.error("Failed to fetch resource information by resource id {}, error {}", resourceId, errorStatus);
370             return Either.right(componentsUtils
371                     .getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
372         }
373         return Either.left(resourceStorageOperationStatusEither.left().value());
374     }
375
376
377     @Override
378     public Either<List<String>, ResponseFormat> deleteMarkedComponents() {
379         return deleteMarkedComponents(ComponentTypeEnum.RESOURCE);
380     }
381
382     @Override
383     public ComponentInstanceBusinessLogic getComponentInstanceBL() {
384         return componentInstanceBusinessLogic;
385     }
386
387     @Override
388     public Either<List<ComponentInstance>, ResponseFormat> getComponentInstancesFilteredByPropertiesAndInputs(String componentId,
389                                                       ComponentTypeEnum componentTypeEnum, String userId, String searchText) {
390         return null;
391     }
392
393     @Override
394     public Either<UiComponentDataTransfer, ResponseFormat> getUiComponentDataTransferByComponentId(String resourceId,
395                                                                     List<String> dataParamsToReturn) {
396         ComponentParametersView paramsToRetuen = new ComponentParametersView(dataParamsToReturn);
397         Either<Resource, StorageOperationStatus> resourceResultEither = toscaOperationFacade.getToscaElement(resourceId,
398                 paramsToRetuen);
399
400         if (resourceResultEither.isRight()) {
401             if (resourceResultEither.right().value().equals(StorageOperationStatus.NOT_FOUND)) {
402                 LOGGER.error("Failed to found resource with id {} ", resourceId);
403                 Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId));
404             }
405
406             LOGGER.error("failed to get resource by id {} with filters {}", resourceId, dataParamsToReturn);
407             return Either.right(componentsUtils.getResponseFormatByResource(
408                     componentsUtils.convertFromStorageResponse(resourceResultEither.right().value()), ""));
409         }
410
411         Resource resource = resourceResultEither.left().value();
412         UiComponentDataTransfer dataTransfer = UiComponentDataConverter.getUiDataTransferFromResourceByParams(resource,
413                 dataParamsToReturn);
414         return Either.left(dataTransfer);
415     }
416 }