Interface operation feature enhancements
[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 fj.data.Either;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Objects;
29 import java.util.Optional;
30 import java.util.UUID;
31 import java.util.stream.Collectors;
32 import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
33 import org.openecomp.sdc.be.components.validation.InterfaceOperationValidation;
34 import org.openecomp.sdc.be.dao.api.ActionStatus;
35 import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
36 import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
37 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
38 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
39 import org.openecomp.sdc.be.model.ArtifactDefinition;
40 import org.openecomp.sdc.be.model.InterfaceDefinition;
41 import org.openecomp.sdc.be.model.Operation;
42 import org.openecomp.sdc.be.model.User;
43 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
44 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
45 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
46 import org.openecomp.sdc.exception.ResponseFormat;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.springframework.beans.factory.annotation.Autowired;
50 import org.springframework.stereotype.Component;
51
52 @Component("interfaceOperationBusinessLogic")
53 public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
54
55     private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationBusinessLogic.class);
56     private static final String EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION =
57             "Exception occurred during {}. Response is {}";
58     private static final String DELETE_INTERFACE_OPERATION = "deleteInterfaceOperation";
59     private static final String GET_INTERFACE_OPERATION = "getInterfaceOperation";
60     private static final String CREATE_INTERFACE_OPERATION = "createInterfaceOperation";
61     private static final String UPDATE_INTERFACE_OPERATION = "updateInterfaceOperation";
62
63     @Autowired
64     private ArtifactCassandraDao artifactCassandraDao;
65
66     @Autowired
67     private InterfaceOperationValidation interfaceOperationValidation;
68
69     public Either<List<InterfaceDefinition>, ResponseFormat> deleteInterfaceOperation(String componentId,
70             String interfaceId, List<String> operationsToDelete, User user, boolean lock) {
71         validateUserExists(user.getUserId(), DELETE_INTERFACE_OPERATION, true);
72
73         Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither = getComponentDetails(componentId);
74         if (componentEither.isRight()) {
75             return Either.right(componentEither.right().value());
76         }
77         org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
78
79         Either<Boolean, ResponseFormat> lockResult =
80                 lockComponentResult(lock, storedComponent, DELETE_INTERFACE_OPERATION);
81         if (lockResult.isRight()) {
82             return Either.right(lockResult.right().value());
83         }
84
85         try {
86             Optional<InterfaceDefinition> optionalInterface = InterfaceOperationUtils
87                                                                       .getInterfaceDefinitionFromComponentByInterfaceId(
88                                                                               storedComponent, interfaceId);
89             if (!optionalInterface.isPresent()) {
90                 return Either.right(
91                         componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceId));
92             }
93             InterfaceDefinition interfaceDefinition = optionalInterface.get();
94
95             Map<String, Operation> operationsCollection = new HashMap<>();
96             for (String operationId : operationsToDelete) {
97                 Optional<Map.Entry<String, Operation>> optionalOperation =
98                         InterfaceOperationUtils.getOperationFromInterfaceDefinition(interfaceDefinition, operationId);
99                 if (!optionalOperation.isPresent()) {
100                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND,
101                             storedComponent.getUniqueId()));
102                 }
103
104                 Operation storedOperation = optionalOperation.get().getValue();
105                 String artifactUuId = storedOperation.getImplementation().getArtifactUUID();
106                 CassandraOperationStatus cassandraStatus = artifactCassandraDao.deleteArtifact(artifactUuId);
107                 if (cassandraStatus != CassandraOperationStatus.OK) {
108                     ResponseFormat responseFormatByArtifactId = componentsUtils.getResponseFormatByArtifactId(
109                             componentsUtils.convertFromStorageResponse(
110                                     componentsUtils.convertToStorageOperationStatus(cassandraStatus)),
111                             storedOperation.getImplementation().getArtifactDisplayName());
112                     return Either.right(responseFormatByArtifactId);
113                 }
114
115                 operationsCollection.put(operationId, interfaceDefinition.getOperationsMap().get(operationId));
116                 interfaceDefinition.getOperations().remove(operationId);
117             }
118
119             Either<List<InterfaceDefinition>, StorageOperationStatus> deleteOperationEither =
120                     interfaceOperation.updateInterfaces(storedComponent.getUniqueId(),
121                             Collections.singletonList(interfaceDefinition));
122             if (deleteOperationEither.isRight()) {
123                 titanDao.rollback();
124                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
125                         deleteOperationEither.right().value(), storedComponent.getComponentType())));
126             }
127
128             if (interfaceDefinition.getOperations().isEmpty()) {
129                 Either<String, StorageOperationStatus> deleteInterfaceEither = interfaceOperation.deleteInterface(
130                         storedComponent.getUniqueId(), interfaceDefinition.getUniqueId());
131                 if (deleteInterfaceEither.isRight()) {
132                     titanDao.rollback();
133                     return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
134                             deleteInterfaceEither.right().value(), storedComponent.getComponentType())));
135                 }
136             }
137
138             titanDao.commit();
139             interfaceDefinition.getOperations().putAll(operationsCollection);
140             interfaceDefinition.getOperations().keySet().removeIf(key -> !(operationsToDelete.contains(key)));
141             return Either.left(Collections.singletonList(interfaceDefinition));
142         } catch (Exception e) {
143             LOGGER.error(EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION, "delete", e);
144             titanDao.rollback();
145             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_DELETED));
146         } finally {
147             if (lockResult.isLeft() && lockResult.left().value()) {
148                 graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
149                         NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
150             }
151         }
152     }
153
154     private Either<org.openecomp.sdc.be.model.Component, ResponseFormat> getComponentDetails(String componentId) {
155         Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentStorageOperationStatusEither =
156                 toscaOperationFacade.getToscaElement(componentId);
157         if (componentStorageOperationStatusEither.isRight()) {
158             return Either.right(componentsUtils.getResponseFormat(
159                     componentsUtils.convertFromStorageResponse(componentStorageOperationStatusEither.right().value())));
160         }
161         return Either.left(componentStorageOperationStatusEither.left().value());
162     }
163
164     private Either<Boolean, ResponseFormat> lockComponentResult(boolean lock,
165             org.openecomp.sdc.be.model.Component component, String action) {
166         if (lock) {
167             Either<Boolean, ResponseFormat> lockResult = lockComponent(component.getUniqueId(), component, action);
168             if (lockResult.isRight()) {
169                 titanDao.rollback();
170                 return Either.right(lockResult.right().value());
171             }
172         }
173         return Either.left(true);
174     }
175
176     public Either<List<InterfaceDefinition>, ResponseFormat> getInterfaceOperation(String componentId,
177             String interfaceId, List<String> operationsToGet, User user, boolean lock) {
178         validateUserExists(user.getUserId(), GET_INTERFACE_OPERATION, true);
179
180         Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither = getComponentDetails(componentId);
181         if (componentEither.isRight()) {
182             return Either.right(componentEither.right().value());
183         }
184         org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
185
186         Either<Boolean, ResponseFormat> lockResult =
187                 lockComponentResult(lock, storedComponent, GET_INTERFACE_OPERATION);
188         if (lockResult.isRight()) {
189             return Either.right(lockResult.right().value());
190         }
191
192         try {
193             Optional<InterfaceDefinition> optionalInterface = InterfaceOperationUtils
194                                                                       .getInterfaceDefinitionFromComponentByInterfaceId(
195                                                                               storedComponent, interfaceId);
196             if (!optionalInterface.isPresent()) {
197                 return Either.right(
198                         componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceId));
199             }
200             InterfaceDefinition interfaceDefinition = optionalInterface.get();
201
202             for (String operationId : operationsToGet) {
203                 Optional<Map.Entry<String, Operation>> optionalOperation =
204                         InterfaceOperationUtils.getOperationFromInterfaceDefinition(interfaceDefinition, operationId);
205                 if (!optionalOperation.isPresent()) {
206                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND,
207                             storedComponent.getUniqueId()));
208                 }
209             }
210
211             titanDao.commit();
212             interfaceDefinition.getOperations().keySet().removeIf(key -> !(operationsToGet.contains(key)));
213             return Either.left(Collections.singletonList(interfaceDefinition));
214         } catch (Exception e) {
215             LOGGER.error(EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION, "get", e);
216             titanDao.rollback();
217             return Either.right(
218                     componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, componentId));
219         } finally {
220             if (lockResult.isLeft() && lockResult.left().value()) {
221                 graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
222                         NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
223             }
224         }
225     }
226
227     public Either<List<InterfaceDefinition>, ResponseFormat> createInterfaceOperation(String componentId,
228             List<InterfaceDefinition> interfaceDefinitions, User user, boolean lock) {
229         return createOrUpdateInterfaceOperation(componentId, interfaceDefinitions, user, false,
230                 CREATE_INTERFACE_OPERATION, lock);
231     }
232
233     private Either<List<InterfaceDefinition>, ResponseFormat> createOrUpdateInterfaceOperation(String componentId,
234             List<InterfaceDefinition> interfaceDefinitions, User user, boolean isUpdate, String errorContext,
235             boolean lock) {
236         validateUserExists(user.getUserId(), errorContext, true);
237
238         Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither = getComponentDetails(componentId);
239         if (componentEither.isRight()) {
240             return Either.right(componentEither.right().value());
241         }
242         org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
243
244         Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock, storedComponent, errorContext);
245         if (lockResult.isRight()) {
246             return Either.right(lockResult.right().value());
247         }
248
249         Either<Map<String, InterfaceDefinition>, ResponseFormat> interfaceLifecycleTypes =
250                 getAllInterfaceLifecycleTypes();
251         if (interfaceLifecycleTypes.isRight()) {
252             return Either.right(interfaceLifecycleTypes.right().value());
253         }
254
255         try {
256             List<InterfaceDefinition> interfacesCollection = new ArrayList<>();
257             Map<String, Operation> operationsCollection = new HashMap<>();
258             for (InterfaceDefinition inputInterfaceDefinition : interfaceDefinitions) {
259                 Optional<InterfaceDefinition> optionalInterface =
260                         InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceType(
261                                 storedComponent, inputInterfaceDefinition.getType());
262                 Either<Boolean, ResponseFormat> interfaceOperationValidationResponseEither =
263                         interfaceOperationValidation
264                                 .validateInterfaceOperations(inputInterfaceDefinition, storedComponent,
265                                         optionalInterface.orElse(null), interfaceLifecycleTypes.left().value(),
266                                         isUpdate);
267                 if (interfaceOperationValidationResponseEither.isRight()) {
268                     return Either.right(interfaceOperationValidationResponseEither.right().value());
269                 }
270
271                 Map<String, Operation> operationsToAddOrUpdate = inputInterfaceDefinition.getOperationsMap();
272                 operationsCollection.putAll(operationsToAddOrUpdate);
273                 inputInterfaceDefinition.getOperations().clear();
274
275                 Either<InterfaceDefinition, ResponseFormat> getInterfaceEither =
276                         getOrCreateInterfaceDefinition(storedComponent, inputInterfaceDefinition,
277                                 optionalInterface.orElse(null));
278                 if (getInterfaceEither.isRight()) {
279                     return Either.right(getInterfaceEither.right().value());
280                 }
281                 InterfaceDefinition interfaceDef = getInterfaceEither.left().value();
282
283                 updateOperationInputDefs(storedComponent, operationsToAddOrUpdate.values());
284
285                 for (Operation operation : operationsToAddOrUpdate.values()) {
286                     if (!isUpdate) {
287                         addOperationToInterface(interfaceDef, operation);
288                     } else {
289                         Optional<Map.Entry<String, Operation>> optionalOperation =
290                                 InterfaceOperationUtils.getOperationFromInterfaceDefinition(interfaceDef,
291                                         operation.getUniqueId());
292                         if (!optionalOperation.isPresent()) {
293                             titanDao.rollback();
294                             return Either.right(componentsUtils
295                                                         .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND,
296                                                                 storedComponent.getUniqueId()));
297                         }
298
299                         Operation storedOperation = optionalOperation.get().getValue();
300                         String artifactUuId = storedOperation.getImplementation().getArtifactUUID();
301                         Either<Long, CassandraOperationStatus> artifactCount =
302                                 artifactCassandraDao.getCountOfArtifactById(artifactUuId);
303                         if (artifactCount.isLeft()) {
304                             CassandraOperationStatus cassandraStatus =
305                                     artifactCassandraDao.deleteArtifact(artifactUuId);
306                             if (cassandraStatus != CassandraOperationStatus.OK) {
307                                 titanDao.rollback();
308                                 ResponseFormat responseFormatByArtifactId =
309                                         componentsUtils.getResponseFormatByArtifactId(
310                                                 componentsUtils.convertFromStorageResponse(
311                                                         componentsUtils.convertToStorageOperationStatus(
312                                                                 cassandraStatus)),
313                                                 storedOperation.getImplementation().getArtifactDisplayName());
314                                 return Either.right(responseFormatByArtifactId);
315                             }
316                         }
317                         updateOperationOnInterface(interfaceDef, operation, artifactUuId);
318                     }
319                 }
320                 interfacesCollection.add(interfaceDef);
321             }
322
323             Either<List<InterfaceDefinition>, StorageOperationStatus> addCreateOperationEither =
324                     interfaceOperation.updateInterfaces(storedComponent.getUniqueId(), interfacesCollection);
325             if (addCreateOperationEither.isRight()) {
326                 titanDao.rollback();
327                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
328                         addCreateOperationEither.right().value(), storedComponent.getComponentType())));
329             }
330
331             titanDao.commit();
332             interfacesCollection.forEach(interfaceDefinition -> interfaceDefinition.getOperations().entrySet().removeIf(
333                     entry -> !operationsCollection.values().stream().map(OperationDataDefinition::getName)
334                                       .collect(Collectors.toList()).contains(entry.getValue().getName())));
335             return Either.left(interfacesCollection);
336         } catch (Exception e) {
337             titanDao.rollback();
338             LOGGER.error(EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION, "addOrUpdate", e);
339             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
340         } finally {
341             if (lockResult.isLeft() && lockResult.left().value()) {
342                 graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
343                         NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
344             }
345         }
346     }
347
348     public Either<Map<String, InterfaceDefinition>, ResponseFormat> getAllInterfaceLifecycleTypes() {
349
350         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> interfaceLifecycleTypes =
351                 interfaceLifecycleTypeOperation.getAllInterfaceLifecycleTypes();
352         if (interfaceLifecycleTypes.isRight()) {
353             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_LIFECYCLE_TYPES_NOT_FOUND));
354         }
355         interfaceLifecycleTypes.left().value().values().forEach(id -> id.setOperations(
356                 id.getOperations().keySet().stream().collect(Collectors.toMap(key -> key.replaceFirst(
357                         id.getUniqueId() + ".", ""), i -> id.getOperations().get(i)))));
358
359         return Either.left(interfaceLifecycleTypes.left().value());
360     }
361
362     private Either<InterfaceDefinition, ResponseFormat> getOrCreateInterfaceDefinition(
363             org.openecomp.sdc.be.model.Component component, InterfaceDefinition interfaceDefinition,
364             InterfaceDefinition storedInterfaceDef) {
365         if (storedInterfaceDef != null) {
366             return Either.left(storedInterfaceDef);
367         } else {
368             interfaceDefinition.setUniqueId(UUID.randomUUID().toString());
369             interfaceDefinition.setToscaResourceName(interfaceDefinition.getType());
370             Either<List<InterfaceDefinition>, StorageOperationStatus> interfaceCreateEither =
371                     interfaceOperation.addInterfaces(component.getUniqueId(),
372                             Collections.singletonList(interfaceDefinition));
373             if (interfaceCreateEither.isRight()) {
374                 titanDao.rollback();
375                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
376                         interfaceCreateEither.right().value(), component.getComponentType())));
377             }
378             return Either.left(interfaceCreateEither.left().value().get(0));
379         }
380     }
381
382     private void updateOperationInputDefs(org.openecomp.sdc.be.model.Component component,
383             Collection<Operation> interfaceOperations) {
384         interfaceOperations.stream().filter(operation -> Objects.nonNull(operation.getInputs())).forEach(
385                 operation -> operation.getInputs().getListToscaDataDefinition().forEach(
386                         inp -> component.getInputs().stream().filter(in -> inp.getInputId().equals(in.getUniqueId()))
387                                        .forEach(in -> {
388                                            inp.setDefaultValue(in.getDefaultValue());
389                                            inp.setValue(in.getValue());
390                                            inp.setSchema(in.getSchema());
391                                        })));
392     }
393
394     private void addOperationToInterface(InterfaceDefinition interfaceDefinition, Operation interfaceOperation) {
395         interfaceOperation.setUniqueId(UUID.randomUUID().toString());
396         interfaceOperation.setImplementation(createArtifactDefinition(UUID.randomUUID().toString()));
397         interfaceDefinition.getOperations()
398                 .put(interfaceOperation.getUniqueId(), new OperationDataDefinition(interfaceOperation));
399     }
400
401     private void updateOperationOnInterface(InterfaceDefinition interfaceDefinition, Operation interfaceOperation,
402             String artifactUuId) {
403         interfaceOperation.setImplementation(createArtifactDefinition(artifactUuId));
404         interfaceDefinition.getOperations()
405                 .put(interfaceOperation.getUniqueId(), new OperationDataDefinition(interfaceOperation));
406     }
407
408     private ArtifactDefinition createArtifactDefinition(String artifactUuId) {
409         ArtifactDefinition artifactDefinition = new ArtifactDefinition();
410         artifactDefinition.setArtifactUUID(artifactUuId);
411         artifactDefinition.setUniqueId(artifactUuId);
412         artifactDefinition.setArtifactType(ArtifactTypeEnum.WORKFLOW.getType());
413         artifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
414         return artifactDefinition;
415     }
416
417     public Either<List<InterfaceDefinition>, ResponseFormat> updateInterfaceOperation(String componentId,
418             List<InterfaceDefinition> interfaceDefinitions, User user, boolean lock) {
419         return createOrUpdateInterfaceOperation(componentId, interfaceDefinitions, user, true,
420                 UPDATE_INTERFACE_OPERATION, lock);
421     }
422
423 }