Allow to delete an interface operation from VFC
[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 package org.openecomp.sdc.be.components.impl;
17
18 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.createMappedCapabilityPropertyDefaultValue;
19 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.createMappedInputPropertyDefaultValue;
20 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.createMappedOutputDefaultValue;
21 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceId;
22 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceType;
23 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationFromInterfaceDefinition;
24 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentInput;
25 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.getPropertyCapabilityFromAllCapProps;
26 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.isCapabilityProperty;
27 import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.SELF;
28
29 import com.google.gson.Gson;
30 import fj.data.Either;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Objects;
39 import java.util.Optional;
40 import java.util.UUID;
41 import java.util.stream.Collectors;
42 import org.apache.commons.collections4.CollectionUtils;
43 import org.apache.commons.collections4.MapUtils;
44 import org.apache.commons.lang3.StringUtils;
45 import org.apache.commons.lang3.tuple.ImmutablePair;
46 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
47 import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
48 import org.openecomp.sdc.be.components.validation.InterfaceOperationValidation;
49 import org.openecomp.sdc.be.dao.api.ActionStatus;
50 import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
51 import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
52 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
53 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
54 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
55 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
56 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
57 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
58 import org.openecomp.sdc.be.model.ArtifactDefinition;
59 import org.openecomp.sdc.be.model.CapabilityDefinition;
60 import org.openecomp.sdc.be.model.Component;
61 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
62 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
63 import org.openecomp.sdc.be.model.InputDefinition;
64 import org.openecomp.sdc.be.model.InterfaceDefinition;
65 import org.openecomp.sdc.be.model.Operation;
66 import org.openecomp.sdc.be.model.User;
67 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
68 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
69 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
70 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
71 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
72 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
73 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
74 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
75 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
76 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
77 import org.openecomp.sdc.exception.ResponseFormat;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
80 import org.springframework.beans.factory.annotation.Autowired;
81
82 @org.springframework.stereotype.Component("interfaceOperationBusinessLogic")
83 public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
84
85     private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationBusinessLogic.class);
86     private static final String EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION = "Exception occurred during {}. Response is {}";
87     private static final String DELETE_INTERFACE_OPERATION = "deleteInterfaceOperation";
88     private static final String GET_INTERFACE_OPERATION = "getInterfaceOperation";
89     private static final String CREATE_INTERFACE_OPERATION = "createInterfaceOperation";
90     private static final String UPDATE_INTERFACE_OPERATION = "updateInterfaceOperation";
91     private final ArtifactCassandraDao artifactCassandraDao;
92     private final InterfaceOperationValidation interfaceOperationValidation;
93
94     @Autowired
95     public InterfaceOperationBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation,
96                                            IGroupInstanceOperation groupInstanceOperation, IGroupTypeOperation groupTypeOperation,
97                                            InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
98                                            ArtifactCassandraDao artifactCassandraDao, InterfaceOperationValidation interfaceOperationValidation,
99                                            ArtifactsOperations artifactToscaOperation) {
100         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
101             artifactToscaOperation);
102         this.artifactCassandraDao = artifactCassandraDao;
103         this.interfaceOperationValidation = interfaceOperationValidation;
104     }
105
106     public Either<List<InterfaceDefinition>, ResponseFormat> deleteInterfaceOperation(String componentId, String interfaceId,
107                                                                                       List<String> operationsToDelete, User user, boolean lock) {
108         validateUserExists(user.getUserId());
109         Either<Component, ResponseFormat> componentEither = getComponentDetails(componentId);
110         if (componentEither.isRight()) {
111             return Either.right(componentEither.right().value());
112         }
113         Component storedComponent = componentEither.left().value();
114         lockComponentResult(lock, storedComponent, DELETE_INTERFACE_OPERATION);
115         try {
116             Optional<InterfaceDefinition> optionalInterface = getInterfaceDefinitionFromComponentByInterfaceId(storedComponent, interfaceId);
117             if (optionalInterface.isEmpty()) {
118                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceId));
119             }
120             InterfaceDefinition interfaceDefinition = optionalInterface.get();
121             Map<String, Operation> operationsCollection = new HashMap<>();
122             for (String operationId : operationsToDelete) {
123                 Optional<Map.Entry<String, Operation>> optionalOperation = getOperationFromInterfaceDefinition(interfaceDefinition, operationId);
124                 if (optionalOperation.isEmpty()) {
125                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, storedComponent.getUniqueId()));
126                 }
127                 Operation storedOperation = optionalOperation.get().getValue();
128                 Either<Boolean, ResponseFormat> validateDeleteOperationContainsNoMappedOutputResponse = interfaceOperationValidation
129                     .validateDeleteOperationContainsNoMappedOutput(storedOperation, storedComponent, interfaceDefinition);
130                 if (validateDeleteOperationContainsNoMappedOutputResponse.isRight()) {
131                     return Either.right(validateDeleteOperationContainsNoMappedOutputResponse.right().value());
132                 }
133                 String artifactUniqueId = storedOperation.getImplementation().getUniqueId();
134                 if (artifactUniqueId != null && !InterfaceOperationUtils.isArtifactInUse(storedComponent, operationId, artifactUniqueId)) {
135                     Either<ArtifactDefinition, StorageOperationStatus> getArtifactEither = artifactToscaOperation
136                         .getArtifactById(storedComponent.getUniqueId(), artifactUniqueId);
137                     if (getArtifactEither.isLeft()) {
138                         Either<ArtifactDefinition, StorageOperationStatus> removeArifactFromComponent = artifactToscaOperation
139                             .removeArifactFromResource(componentId, artifactUniqueId,
140                                 NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()), true);
141                         if (removeArifactFromComponent.isRight()) {
142                             janusGraphDao.rollback();
143                             ResponseFormat responseFormatByArtifactId = componentsUtils
144                                 .getResponseFormatByArtifactId(componentsUtils.convertFromStorageResponse(removeArifactFromComponent.right().value()),
145                                     storedOperation.getImplementation().getArtifactDisplayName());
146                             return Either.right(responseFormatByArtifactId);
147                         }
148                         CassandraOperationStatus cassandraStatus = artifactCassandraDao.deleteArtifact(artifactUniqueId);
149                         if (cassandraStatus != CassandraOperationStatus.OK) {
150                             janusGraphDao.rollback();
151                             ResponseFormat responseFormatByArtifactId = componentsUtils.getResponseFormatByArtifactId(
152                                 componentsUtils.convertFromStorageResponse(componentsUtils.convertToStorageOperationStatus(cassandraStatus)),
153                                 storedOperation.getImplementation().getArtifactDisplayName());
154                             return Either.right(responseFormatByArtifactId);
155                         }
156                     }
157                 }
158                 operationsCollection.put(operationId, interfaceDefinition.getOperationsMap().get(operationId));
159                 final Optional<String> operationKeyOptional = interfaceDefinition.getOperations().entrySet()
160                     .stream().filter(entry -> operationId.equals(entry.getValue().getUniqueId()))
161                     .map(Entry::getKey).findFirst();
162                 if (operationKeyOptional.isEmpty()) {
163                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, storedComponent.getUniqueId()));
164                 }
165                 interfaceDefinition.getOperations().remove(operationKeyOptional.get());
166             }
167             final Either<List<InterfaceDefinition>, StorageOperationStatus> updateInterfaceResultEither;
168             updateInterfaceResultEither = interfaceOperation.updateInterfaces(storedComponent, Collections.singletonList(interfaceDefinition));
169             if (updateInterfaceResultEither.isRight()) {
170                 janusGraphDao.rollback();
171                 return Either.right(componentsUtils.getResponseFormat(
172                     componentsUtils.convertFromStorageResponse(updateInterfaceResultEither.right().value(), storedComponent.getComponentType())));
173             }
174             if (interfaceDefinition.getOperations().isEmpty()) {
175                 final var deleteInterfaceEither = interfaceOperation.deleteInterface(storedComponent, interfaceDefinition.getUniqueId());
176                 if (deleteInterfaceEither.isRight()) {
177                     janusGraphDao.rollback();
178                     return Either.right(componentsUtils.getResponseFormat(
179                         componentsUtils.convertFromStorageResponse(deleteInterfaceEither.right().value(), storedComponent.getComponentType())));
180                 }
181             }
182             janusGraphDao.commit();
183             interfaceDefinition.getOperations().putAll(operationsCollection);
184             interfaceDefinition.getOperations().keySet().removeIf(key -> !(operationsToDelete.contains(key)));
185             return Either.left(Collections.singletonList(interfaceDefinition));
186         } catch (Exception e) {
187             LOGGER.error(EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION, "delete", e);
188             janusGraphDao.rollback();
189             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_DELETED));
190         } finally {
191             graphLockOperation
192                 .unlockComponent(storedComponent.getUniqueId(), NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
193         }
194     }
195
196     private Either<Component, ResponseFormat> getComponentDetails(String componentId) {
197         Either<Component, StorageOperationStatus> componentStorageOperationStatusEither = toscaOperationFacade
198             .getToscaElement(componentId);
199         if (componentStorageOperationStatusEither.isRight()) {
200             return Either.right(
201                 componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentStorageOperationStatusEither.right().value())));
202         }
203         return Either.left(componentStorageOperationStatusEither.left().value());
204     }
205
206     private Either<Boolean, ResponseFormat> lockComponentResult(boolean lock, Component component, String action) {
207         if (lock) {
208             try {
209                 lockComponent(component.getUniqueId(), component, action);
210             } catch (ComponentException e) {
211                 janusGraphDao.rollback();
212                 throw e;
213             }
214         }
215         return Either.left(true);
216     }
217
218     public Either<List<InterfaceDefinition>, ResponseFormat> getInterfaceOperation(String componentId, String interfaceId,
219                                                                                    List<String> operationsToGet, User user, boolean lock) {
220         validateUserExists(user);
221         Either<Component, ResponseFormat> componentEither = getComponentDetails(componentId);
222         if (componentEither.isRight()) {
223             return Either.right(componentEither.right().value());
224         }
225         Component storedComponent = componentEither.left().value();
226         lockComponentResult(lock, storedComponent, GET_INTERFACE_OPERATION);
227         try {
228             Optional<InterfaceDefinition> optionalInterface = getInterfaceDefinitionFromComponentByInterfaceId(storedComponent, interfaceId);
229             if (!optionalInterface.isPresent()) {
230                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceId));
231             }
232             InterfaceDefinition interfaceDefinition = optionalInterface.get();
233             for (String operationId : operationsToGet) {
234                 Optional<Map.Entry<String, Operation>> optionalOperation = getOperationFromInterfaceDefinition(interfaceDefinition, operationId);
235                 if (!optionalOperation.isPresent()) {
236                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, storedComponent.getUniqueId()));
237                 }
238             }
239             janusGraphDao.commit();
240             interfaceDefinition.getOperations().keySet().removeIf(key -> !(operationsToGet.contains(key)));
241             return Either.left(Collections.singletonList(interfaceDefinition));
242         } catch (Exception e) {
243             LOGGER.error(EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION, "get", e);
244             janusGraphDao.rollback();
245             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, componentId));
246         } finally {
247             graphLockOperation
248                 .unlockComponent(storedComponent.getUniqueId(), NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
249         }
250     }
251
252     public Either<List<InterfaceDefinition>, ResponseFormat> createInterfaceOperation(String componentId,
253                                                                                       List<InterfaceDefinition> interfaceDefinitions, User user,
254                                                                                       boolean lock) {
255         return createOrUpdateInterfaceOperation(componentId, interfaceDefinitions, user, false, CREATE_INTERFACE_OPERATION, lock);
256     }
257
258     private Either<List<InterfaceDefinition>, ResponseFormat> createOrUpdateInterfaceOperation(String componentId,
259                                                                                                List<InterfaceDefinition> interfaceDefinitions,
260                                                                                                User user, boolean isUpdate, String errorContext,
261                                                                                                boolean lock) {
262         validateUserExists(user);
263         Either<Component, ResponseFormat> componentEither = getComponentDetails(componentId);
264         if (componentEither.isRight()) {
265             return Either.right(componentEither.right().value());
266         }
267         Component storedComponent = componentEither.left().value();
268         lockComponentResult(lock, storedComponent, errorContext);
269         Either<Map<String, InterfaceDefinition>, ResponseFormat> interfaceLifecycleTypes = getAllInterfaceLifecycleTypes(storedComponent.getModel());
270         if (interfaceLifecycleTypes.isRight()) {
271             return Either.right(interfaceLifecycleTypes.right().value());
272         }
273         try {
274             List<InterfaceDefinition> interfacesCollection = new ArrayList<>();
275             Map<String, Operation> operationsCollection = new HashMap<>();
276             for (InterfaceDefinition inputInterfaceDefinition : interfaceDefinitions) {
277                 Optional<InterfaceDefinition> optionalInterface = getInterfaceDefinitionFromComponentByInterfaceType(storedComponent,
278                     inputInterfaceDefinition.getType());
279                 Either<Boolean, ResponseFormat> interfaceOperationValidationResponseEither = interfaceOperationValidation
280                     .validateInterfaceOperations(inputInterfaceDefinition, storedComponent, optionalInterface.orElse(null),
281                         interfaceLifecycleTypes.left().value(), isUpdate);
282                 if (interfaceOperationValidationResponseEither.isRight()) {
283                     return Either.right(interfaceOperationValidationResponseEither.right().value());
284                 }
285                 Map<String, Operation> operationsToAddOrUpdate = inputInterfaceDefinition.getOperationsMap();
286                 operationsCollection.putAll(operationsToAddOrUpdate);
287                 inputInterfaceDefinition.getOperations().clear();
288                 Either<InterfaceDefinition, ResponseFormat> getInterfaceEither = getOrCreateInterfaceDefinition(storedComponent,
289                     inputInterfaceDefinition, optionalInterface.orElse(null));
290                 if (getInterfaceEither.isRight()) {
291                     return Either.right(getInterfaceEither.right().value());
292                 }
293                 InterfaceDefinition interfaceDef = getInterfaceEither.left().value();
294                 updateOperationInputDefs(storedComponent, operationsToAddOrUpdate.values());
295                 for (Operation operation : operationsToAddOrUpdate.values()) {
296                     if (!isUpdate) {
297                         addOperationToInterface(interfaceDef, operation);
298                     } else {
299                         Optional<Map.Entry<String, Operation>> optionalOperation = getOperationFromInterfaceDefinition(interfaceDef,
300                             operation.getUniqueId());
301                         if (optionalOperation.isEmpty()) {
302                             janusGraphDao.rollback();
303                             return Either
304                                 .right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, storedComponent.getUniqueId()));
305                         }
306                         final Operation storedOperation = optionalOperation.get().getValue();
307                         final ArtifactDataDefinition implementation = storedOperation.getImplementation();
308                         final String artifactUniqueId = implementation.getUniqueId();
309                         if (StringUtils.isNotEmpty(artifactUniqueId)) {
310                             if (!InterfaceOperationUtils.isArtifactInUse(storedComponent, storedOperation.getUniqueId(), artifactUniqueId)) {
311                                 Either<ArtifactDefinition, StorageOperationStatus> getArtifactEither = artifactToscaOperation
312                                     .getArtifactById(storedComponent.getUniqueId(), artifactUniqueId);
313                                 if (getArtifactEither.isLeft()) {
314                                     Either<ArtifactDefinition, StorageOperationStatus> removeArifactFromComponent = artifactToscaOperation
315                                         .removeArifactFromResource(componentId, artifactUniqueId,
316                                             NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()), true);
317                                     if (removeArifactFromComponent.isRight()) {
318                                         janusGraphDao.rollback();
319                                         ResponseFormat responseFormatByArtifactId = componentsUtils.getResponseFormatByArtifactId(
320                                             componentsUtils.convertFromStorageResponse(removeArifactFromComponent.right().value()),
321                                             implementation.getArtifactDisplayName());
322                                         return Either.right(responseFormatByArtifactId);
323                                     }
324                                     CassandraOperationStatus cassandraStatus = artifactCassandraDao.deleteArtifact(artifactUniqueId);
325                                     if (cassandraStatus != CassandraOperationStatus.OK) {
326                                         janusGraphDao.rollback();
327                                         ResponseFormat responseFormatByArtifactId = componentsUtils.getResponseFormatByArtifactId(
328                                             componentsUtils.convertFromStorageResponse(
329                                                 componentsUtils.convertToStorageOperationStatus(cassandraStatus)),
330                                             implementation.getArtifactDisplayName());
331                                         return Either.right(responseFormatByArtifactId);
332                                     }
333                                 }
334                             }
335                         }
336                         updateOperationOnInterface(interfaceDef, operation, implementation.getArtifactUUID());
337                     }
338                 }
339                 interfacesCollection.add(interfaceDef);
340             }
341             final var addCreateOperationEither = interfaceOperation.updateInterfaces(storedComponent, interfacesCollection);
342             if (addCreateOperationEither.isRight()) {
343                 janusGraphDao.rollback();
344                 return Either.right(componentsUtils.getResponseFormat(
345                     componentsUtils.convertFromStorageResponse(addCreateOperationEither.right().value(), storedComponent.getComponentType())));
346             }
347             janusGraphDao.commit();
348             interfacesCollection.forEach(interfaceDefinition -> interfaceDefinition.getOperations().entrySet().removeIf(
349                 entry -> !operationsCollection.values().stream().map(OperationDataDefinition::getName).collect(Collectors.toList())
350                     .contains(entry.getValue().getName())));
351             return Either.left(interfacesCollection);
352         } catch (Exception e) {
353             janusGraphDao.rollback();
354             LOGGER.error(EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION, "addOrUpdate", e);
355             return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
356         } finally {
357             graphLockOperation
358                 .unlockComponent(storedComponent.getUniqueId(), NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
359         }
360     }
361
362     public Either<Map<String, InterfaceDefinition>, ResponseFormat> getAllInterfaceLifecycleTypes(final String model) {
363         Either<Map<String, InterfaceDefinition>, StorageOperationStatus> interfaceLifecycleTypes = interfaceLifecycleTypeOperation
364             .getAllInterfaceLifecycleTypes(model);
365         if (interfaceLifecycleTypes.isRight()) {
366             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_LIFECYCLE_TYPES_NOT_FOUND));
367         }
368         interfaceLifecycleTypes.left().value().values().forEach(id -> id.setOperations(id.getOperations().keySet().stream()
369             .collect(Collectors.toMap(key -> key.replaceFirst(id.getUniqueId() + ".", ""), i -> id.getOperations().get(i)))));
370         return Either.left(interfaceLifecycleTypes.left().value());
371     }
372
373     private Either<InterfaceDefinition, ResponseFormat> getOrCreateInterfaceDefinition(Component component,
374                                                                                        InterfaceDefinition interfaceDefinition,
375                                                                                        InterfaceDefinition storedInterfaceDef) {
376         if (storedInterfaceDef != null) {
377             return Either.left(storedInterfaceDef);
378         }
379         interfaceDefinition.setUniqueId(UUID.randomUUID().toString());
380         interfaceDefinition.setToscaResourceName(interfaceDefinition.getType());
381         final var interfaceCreateEither = interfaceOperation.addInterfaces(component, Collections.singletonList(interfaceDefinition));
382         if (interfaceCreateEither.isRight()) {
383             janusGraphDao.rollback();
384             return Either.right(componentsUtils
385                 .getResponseFormat(componentsUtils.convertFromStorageResponse(interfaceCreateEither.right().value(), component.getComponentType())));
386         }
387         return Either.left(interfaceCreateEither.left().value().get(0));
388     }
389
390     private void updateOperationInputDefs(Component component, Collection<Operation> interfaceOperations) {
391         interfaceOperations.stream().filter(operation -> Objects.nonNull(operation.getInputs())).forEach(
392             operation -> operation.getInputs().getListToscaDataDefinition()
393                 .forEach(inp -> component.getInputs().forEach(in -> updateOperationInputDefinition(component, inp, in))));
394     }
395
396     private void updateOperationInputDefinition(Component component, OperationInputDefinition operationInput,
397                                                 InputDefinition componentInput) {
398         if (operationInput.getInputId().equals(componentInput.getUniqueId())) {
399             //Set the default value, value and schema only for inputs mapped to component inputs
400             operationInput.setDefaultValue(componentInput.getDefaultValue());
401             operationInput.setToscaDefaultValue(getInputToscaDefaultValue(operationInput, component));
402             operationInput.setValue(componentInput.getValue());
403             operationInput.setSchema(componentInput.getSchema());
404             operationInput.setParentPropertyType(componentInput.getParentPropertyType());
405             operationInput.setSubPropertyInputPath(componentInput.getSubPropertyInputPath());
406         }
407         //Set the tosca default value for inputs mapped to component inputs as well as other outputs
408         operationInput.setToscaDefaultValue(getInputToscaDefaultValue(operationInput, component));
409     }
410
411     private String getInputToscaDefaultValue(OperationInputDefinition input, Component component) {
412         Map<String, List<String>> defaultInputValue = null;
413         if (isOperationInputMappedToComponentInput(input, component.getInputs())) {
414             String propertyName = input.getInputId().substring(input.getInputId().indexOf('.') + 1);
415             setParentPropertyTypeAndInputPath(input, component);
416             defaultInputValue = createMappedInputPropertyDefaultValue(propertyName);
417         } else if (isCapabilityProperty(input.getInputId(), component).isPresent()) {
418             Optional<ComponentInstanceProperty> instancePropertyOpt = isCapabilityProperty(input.getInputId(), component);
419             Optional<String> parentPropertyIdOpt = instancePropertyOpt.map(PropertyDataDefinition::getParentUniqueId);
420             Map<String, List<CapabilityDefinition>> componentCapabilities = component.getCapabilities();
421             if (MapUtils.isNotEmpty(componentCapabilities)) {
422                 List<CapabilityDefinition> capabilityDefinitionList = componentCapabilities.values().stream().flatMap(Collection::stream)
423                     .filter(capabilityDefinition -> capabilityDefinition.getOwnerId().equals(component.getUniqueId())).collect(Collectors.toList());
424                 defaultInputValue = parentPropertyIdOpt
425                     .flatMap(parentPropertyId -> getPropertyCapabilityFromAllCapProps(parentPropertyId, capabilityDefinitionList)).flatMap(
426                         capability -> instancePropertyOpt
427                             .map(instanceProperty -> new ImmutablePair<>(capability.getName(), instanceProperty.getName()))).map(tuple -> {
428                         String propertyName = tuple.right;
429                         String capabilityName = tuple.left;
430                         return createMappedCapabilityPropertyDefaultValue(capabilityName, propertyName);
431                     }).orElse(null);
432             }
433         } else {
434             //Currently inputs can only be mapped to a declared input or an other operation outputs
435             defaultInputValue = createMappedOutputDefaultValue(SELF, input.getInputId());
436         }
437         return new Gson().toJson(defaultInputValue);
438     }
439
440     private void setParentPropertyTypeAndInputPath(OperationInputDefinition input, Component component) {
441         if (CollectionUtils.isEmpty(component.getInputs())) {
442             return;
443         }
444         component.getInputs().stream().filter(inp -> inp.getUniqueId().equals(input.getInputId().substring(0, input.getInputId().lastIndexOf('.'))))
445             .forEach(inp -> {
446                 input.setParentPropertyType(inp.getParentPropertyType());
447                 if (Objects.nonNull(input.getName())) {
448                     input.setSubPropertyInputPath(input.getName().replaceAll("\\.", "#"));
449                 }
450             });
451     }
452
453     private void addOperationToInterface(InterfaceDefinition interfaceDefinition, Operation interfaceOperation) {
454         interfaceOperation.setUniqueId(UUID.randomUUID().toString());
455         interfaceOperation.setImplementation(createArtifactDefinition(UUID.randomUUID().toString(), interfaceOperation));
456         interfaceDefinition.getOperations().put(interfaceOperation.getUniqueId(), new OperationDataDefinition(interfaceOperation));
457     }
458
459     private void updateOperationOnInterface(InterfaceDefinition interfaceDefinition, Operation interfaceOperation, String artifactUuId) {
460         interfaceOperation.setImplementation(createArtifactDefinition(artifactUuId, interfaceOperation));
461         interfaceDefinition.getOperations().put(interfaceOperation.getUniqueId(), new OperationDataDefinition(interfaceOperation));
462     }
463
464     private ArtifactDefinition createArtifactDefinition(String artifactUuId, Operation operation) {
465         ArtifactDefinition artifactDefinition = new ArtifactDefinition();
466         artifactDefinition.setArtifactUUID(artifactUuId);
467         artifactDefinition.setUniqueId(artifactUuId);
468         artifactDefinition.setEsId(artifactUuId);
469         artifactDefinition.setArtifactType(ArtifactTypeEnum.WORKFLOW.getType());
470         artifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
471         artifactDefinition.setArtifactLabel(operation.getName() + ".workflowArtifact");
472         artifactDefinition.setArtifactName(operation.getWorkflowName() + "_" + operation.getWorkflowVersion());
473         return artifactDefinition;
474     }
475
476     public Either<List<InterfaceDefinition>, ResponseFormat> updateInterfaceOperation(String componentId,
477                                                                                       List<InterfaceDefinition> interfaceDefinitions, User user,
478                                                                                       boolean lock) {
479         return createOrUpdateInterfaceOperation(componentId, interfaceDefinitions, user, true, UPDATE_INTERFACE_OPERATION, lock);
480     }
481
482     public Either<List<OperationInputDefinition>, ResponseFormat> getInputsListForOperation(String componentId, String componentInstanceId,
483                                                                                             String interfaceId, String operationId, User user) {
484         Either<Component, ResponseFormat> componentEither = getComponentDetails(componentId);
485         if (componentEither.isRight()) {
486             return Either.right(componentEither.right().value());
487         }
488         Component storedComponent = componentEither.left().value();
489         validateUserExists(user.getUserId());
490         Either<Boolean, ResponseFormat> lockResult = lockComponentResult(true, storedComponent, GET_INTERFACE_OPERATION);
491         if (lockResult.isRight()) {
492             return Either.right(lockResult.right().value());
493         }
494         try {
495             Component parentComponent = componentEither.left().value();
496             Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = parentComponent.getComponentInstancesInterfaces();
497             if (MapUtils.isEmpty(componentInstanceInterfaces)) {
498                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, componentInstanceId));
499             }
500             List<ComponentInstanceInterface> componentInstanceInterfaceList = componentInstanceInterfaces.get(componentInstanceId);
501             for (ComponentInstanceInterface componentInstanceInterface : componentInstanceInterfaceList) {
502                 if (componentInstanceInterface.getInterfaceId().equals(interfaceId)) {
503                     Map<String, OperationDataDefinition> operations = componentInstanceInterface.getOperations();
504                     if (MapUtils.isNotEmpty(operations) && operations.containsKey(operationId)) {
505                         ListDataDefinition<OperationInputDefinition> inputs = operations.get(operationId).getInputs();
506                         return Either.left(
507                             CollectionUtils.isEmpty(inputs.getListToscaDataDefinition()) ? new ArrayList<>() : inputs.getListToscaDataDefinition());
508                     }
509                 }
510             }
511             return Either.left(new ArrayList<>());
512         } catch (Exception e) {
513             LOGGER.error(EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION, "get", e);
514             janusGraphDao.rollback();
515             return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND));
516         } finally {
517             if (lockResult.isLeft() && lockResult.left().value()) {
518                 graphLockOperation
519                     .unlockComponent(storedComponent.getUniqueId(), NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
520             }
521         }
522     }
523 }