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