+ public Either<List<Operation>, ResponseFormat> addServiceConsumptionData(String serviceId, String serviceInstanceId, String operationId,
+ List<ServiceConsumptionData> serviceConsumptionDataList, String userId) {
+ List<Operation> operationList = new ArrayList<>();
+ Either<Service, StorageOperationStatus> serviceEither = toscaOperationFacade.getToscaElement(serviceId);
+ if (serviceEither.isRight()) {
+ return Either.right(componentsUtils.getResponseFormat(serviceEither.right().value()));
+ }
+ Service service = serviceEither.left().value();
+ StorageOperationStatus storageOperationStatus = graphLockOperation.lockComponent(service.getUniqueId(), NodeTypeEnum.Service);
+ if (storageOperationStatus != StorageOperationStatus.OK) {
+ return Either.right(componentsUtils.getResponseFormat(storageOperationStatus));
+ }
+ try {
+ for (ServiceConsumptionData serviceConsumptionData : serviceConsumptionDataList) {
+ Either<Operation, ResponseFormat> operationEither = addPropertyServiceConsumption(serviceId, serviceInstanceId, operationId, userId,
+ serviceConsumptionData);
+ if (operationEither.isRight()) {
+ return Either.right(operationEither.right().value());
+ }
+ operationList.add(operationEither.left().value());
+ }
+ janusGraphDao.commit();
+ return Either.left(operationList);
+ } catch (Exception e) {
+ janusGraphDao.rollback();
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+ } finally {
+ graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service);
+ }
+ }
+
+ public Either<Operation, ResponseFormat> addPropertyServiceConsumption(String serviceId, String serviceInstanceId, String operationId,
+ String userId, ServiceConsumptionData serviceConsumptionData) {
+ validateUserExists(userId);
+ Either<Service, StorageOperationStatus> serviceEither = toscaOperationFacade.getToscaElement(serviceId);
+ if (serviceEither.isRight()) {
+ return Either.right(componentsUtils.getResponseFormat(serviceEither.right().value()));
+ }
+ Service parentService = serviceEither.left().value();
+ List<ComponentInstance> componentInstances = parentService.getComponentInstances();
+ if (CollectionUtils.isEmpty(componentInstances)) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+ }
+ Optional<ComponentInstance> serviceInstanceCandidate = componentInstances.stream()
+ .filter(instance -> instance.getUniqueId().equals(serviceInstanceId)).findAny();
+ if (!serviceInstanceCandidate.isPresent()) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+ }
+ Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces = parentService.getComponentInstancesInterfaces();
+ if (MapUtils.isEmpty(componentInstancesInterfaces)) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+ }
+ List<InterfaceDefinition> interfaces = new ArrayList<>();
+ for (ComponentInstanceInterface componentInstanceInterface : componentInstancesInterfaces.get(serviceInstanceId)) {
+ interfaces.add(componentInstanceInterface);
+ }
+ ComponentInstance serviceInstance = serviceInstanceCandidate.get();
+ Optional<InterfaceDefinition> interfaceCandidate = InterfaceOperationUtils.getInterfaceDefinitionFromOperationId(interfaces, operationId);
+ if (!interfaceCandidate.isPresent()) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+ }
+ InterfaceDefinition interfaceDefinition = interfaceCandidate.get();
+ Map<String, Operation> operations = interfaceDefinition.getOperationsMap();
+ if (MapUtils.isEmpty(operations)) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+ }
+ Operation operation = operations.get(operationId);
+ Either<Operation, ResponseFormat> operationEither = Either.left(operation);
+ ListDataDefinition<OperationInputDefinition> inputs = operation.getInputs();
+ Optional<OperationInputDefinition> inputCandidate = getOperationInputByInputId(serviceConsumptionData, inputs);
+ if (!inputCandidate.isPresent()) {
+ return Either.right(new ResponseFormat(HttpStatus.NOT_FOUND.value()));
+ }
+ OperationInputDefinition operationInputDefinition = inputCandidate.get();
+ // add data to operation
+ if (Objects.nonNull(serviceConsumptionData.getValue())) {
+ operationEither = handleConsumptionValue(parentService, serviceInstanceId, serviceConsumptionData, operation, operationInputDefinition);
+ }
+ if (operationEither.isRight()) {
+ return Either.right(operationEither.right().value());
+ }
+ Operation updatedOperation = operationEither.left().value();
+ operations.remove(operationId);
+ operations.put(operationId, updatedOperation);
+ interfaceDefinition.setOperationsMap(operations);
+ parentService.getComponentInstances().remove(serviceInstance);
+ if (CollectionUtils.isEmpty(parentService.getComponentInstances())) {
+ parentService.setComponentInstances(new ArrayList<>());
+ }
+ Map<String, Object> instanceInterfaces =
+ MapUtils.isEmpty(serviceInstance.getInterfaces()) ? new HashMap<>() : serviceInstance.getInterfaces();
+ instanceInterfaces.remove(interfaceDefinition.getUniqueId());
+ instanceInterfaces.put(interfaceDefinition.getUniqueId(), interfaceDefinition);
+ serviceInstance.setInterfaces(instanceInterfaces);
+ removeComponentInstanceInterfaceByInterfaceId(interfaceDefinition.getUniqueId(), componentInstancesInterfaces.get(serviceInstanceId));
+ componentInstancesInterfaces.get(serviceInstanceId)
+ .add(new ComponentInstanceInterface(interfaceDefinition.getUniqueId(), interfaceDefinition));
+ parentService.getComponentInstances().add(serviceInstance);
+ StorageOperationStatus status = toscaOperationFacade.updateComponentInstanceInterfaces(parentService, serviceInstanceId);
+ if (status != StorageOperationStatus.OK) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+ }
+ return Either.left(operation);
+ }
+
+ private void removeComponentInstanceInterfaceByInterfaceId(String interfaceIdToRemove, List<ComponentInstanceInterface> instanceInterfaces) {
+ if (CollectionUtils.isEmpty(instanceInterfaces)) {
+ return;
+ }
+ Optional<ComponentInstanceInterface> interfaceToRemove = instanceInterfaces.stream()
+ .filter(instInterface -> instInterface.getUniqueId().equals(interfaceIdToRemove)).findAny();
+ if (interfaceToRemove.isPresent()) {
+ instanceInterfaces.remove(interfaceToRemove.get());
+ }
+ }
+
+ private Either<Operation, ResponseFormat> handleConsumptionValue(Service containerService, String serviceInstanceId,
+ ServiceConsumptionData serviceConsumptionData, Operation operation,
+ OperationInputDefinition operationInputDefinition) {
+ String source = serviceConsumptionData.getSource();
+ String consumptionValue = serviceConsumptionData.getValue();
+ String type = serviceConsumptionData.getType();
+ String operationIdentifier =
+ consumptionValue.contains(".") ? consumptionValue.substring(0, consumptionValue.lastIndexOf('.')) : consumptionValue;
+ ServiceConsumptionSource sourceValue = ServiceConsumptionSource.getSourceValue(source);
+ if (STATIC.equals(sourceValue)) {
+ // Validate constraint on input value
+ Either<Boolean, ResponseFormat> constraintValidationResult = validateOperationInputConstraint(operationInputDefinition, consumptionValue,
+ type, containerService.getModel());
+ if (constraintValidationResult.isRight()) {
+ return Either.right(constraintValidationResult.right().value());
+ }
+ return handleConsumptionStaticValue(consumptionValue, type, operation, operationInputDefinition, containerService.getModel());
+ }
+ if (Objects.isNull(sourceValue)) {
+ List<PropertyDefinition> propertyDefinitions;
+ Map<String, List<CapabilityDefinition>> capabilities = null;
+ String componentName;
+ List<OperationOutputDefinition> outputs = null;
+ if (source.equals(containerService.getUniqueId())) {
+ Either<Service, StorageOperationStatus> serviceToTakePropEither = toscaOperationFacade.getToscaElement(source);
+ if (serviceToTakePropEither.isRight()) {
+ return Either.right(componentsUtils.getResponseFormat(serviceToTakePropEither.right().value()));
+ }
+ Service service = serviceToTakePropEither.left().value();
+ operationInputDefinition.setSource(service.getUniqueId());
+ sourceValue = SERVICE_INPUT;
+ propertyDefinitions = service.getProperties();
+ componentName = service.getName();
+ outputs = InterfaceOperationUtils.getOtherOperationOutputsOfComponent(operationIdentifier, service.getInterfaces())
+ .getListToscaDataDefinition();
+ } else {
+ Optional<ComponentInstance> getComponentInstance = containerService.getComponentInstanceById(source);
+ if (!getComponentInstance.isPresent()) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, source));
+ }
+ ComponentInstance componentInstance = getComponentInstance.get();
+ operationInputDefinition.setSource(componentInstance.getUniqueId());
+ propertyDefinitions = componentInstance.getProperties();
+ capabilities = componentInstance.getCapabilities();
+ componentName = source.equals(serviceInstanceId) ? SELF : componentInstance.getName();
+ if (MapUtils.isNotEmpty(componentInstance.getInterfaces())) {
+ Map<String, InterfaceDataDefinition> componentInstanceInterfaces = componentInstance.getInterfaces().entrySet().stream()
+ .collect(Collectors.toMap((Map.Entry::getKey), (interfaceEntry -> (InterfaceDataDefinition) interfaceEntry.getValue())));
+ outputs = InterfaceOperationUtils.getOtherOperationOutputsOfComponent(operationIdentifier, componentInstanceInterfaces)
+ .getListToscaDataDefinition();
+ }
+ }
+ if (sourceValue == ServiceConsumptionSource.SERVICE_INPUT) {
+ //The operation input in service consumption has been mapped to an input in the parent service
+ return handleConsumptionInputValue(consumptionValue, containerService, operation, operationInputDefinition);
+ }
+ return handleConsumptionPropertyValue(operation, operationInputDefinition, serviceConsumptionData, propertyDefinitions, capabilities,
+ outputs, componentName);
+ }
+ operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.SOURCE, source);
+ operationInputDefinition.setSource(source);
+ return Either.left(operation);
+ }
+
+ private Optional<OperationInputDefinition> getOperationInputByInputId(ServiceConsumptionData serviceConsumptionData,
+ ListDataDefinition<OperationInputDefinition> inputs) {
+ if (CollectionUtils.isEmpty(inputs.getListToscaDataDefinition())) {
+ return Optional.empty();
+ }
+ return inputs.getListToscaDataDefinition().stream()
+ .filter(operationInput -> operationInput.getInputId().equals(serviceConsumptionData.getInputId())).findAny();
+ }
+
+ private Either<Operation, ResponseFormat> handleConsumptionPropertyValue(Operation operation, OperationInputDefinition operationInputDefinition,
+ ServiceConsumptionData serviceConsumptionData,
+ List<PropertyDefinition> properties,
+ Map<String, List<CapabilityDefinition>> capabilities,
+ List<OperationOutputDefinition> outputs, String componentName) {
+ if (CollectionUtils.isEmpty(properties) && CollectionUtils.isEmpty(outputs)) {
+ return Either.left(operation);
+ }
+ String consumptionValue = serviceConsumptionData.getValue();
+ if (CollectionUtils.isNotEmpty(outputs) && isOperationInputMappedToOtherOperationOutput(getOperationOutputName(consumptionValue), outputs)) {
+ return handleConsumptionInputMappedToOperationOutput(operation, operationInputDefinition, outputs, consumptionValue, componentName);
+ }
+ if (CollectionUtils.isNotEmpty(properties) && PropertiesUtils.isNodeProperty(consumptionValue, properties)) {
+ return handleConsumptionInputMappedToProperty(operation, operationInputDefinition, serviceConsumptionData, properties, componentName);
+ }
+ if (MapUtils.isNotEmpty(capabilities)) {
+ return handleConsumptionInputMappedToCapabilityProperty(operation, operationInputDefinition, serviceConsumptionData, capabilities,
+ componentName);
+ }
+ return Either.left(operation);
+ }
+
+ private Either<Operation, ResponseFormat> handleConsumptionInputMappedToProperty(Operation operation,
+ OperationInputDefinition operationInputDefinition,
+ ServiceConsumptionData serviceConsumptionData,
+ List<PropertyDefinition> properties, String componentName) {
+ Optional<PropertyDefinition> servicePropertyCandidate = properties.stream()
+ .filter(property -> property.getName().equals(serviceConsumptionData.getValue())).findAny();
+ if (servicePropertyCandidate.isPresent()) {
+ boolean isInputTypeSimilarToOperation = isAssignedValueFromValidType(operationInputDefinition.getType(), servicePropertyCandidate.get());
+ if (!isInputTypeSimilarToOperation) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
+ }
+ addPropertyToInputValue(componentName, operation, operationInputDefinition, servicePropertyCandidate.get());
+ }
+ return Either.left(operation);
+ }
+
+ private Either<Operation, ResponseFormat> handleConsumptionInputMappedToOperationOutput(Operation operation,
+ OperationInputDefinition operationInputDefinition,
+ List<OperationOutputDefinition> outputs,
+ String consumptionValue, String componentName) {
+ String outputName = getOperationOutputName(consumptionValue);
+ Optional<OperationOutputDefinition> servicePropertyOutputCandidate = outputs.stream().filter(output -> output.getName().equals(outputName))
+ .findAny();
+ if (servicePropertyOutputCandidate.isPresent()) {
+ boolean isInputTypeSimilarToOperation = isAssignedValueFromValidType(operationInputDefinition.getType(),
+ servicePropertyOutputCandidate.get());
+ if (!isInputTypeSimilarToOperation) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
+ }
+ addOutputToInputValue(componentName, consumptionValue, operation, operationInputDefinition);
+ }
+ return Either.left(operation);
+ }
+
+ private void addPropertyToInputValue(String componentName, Operation operation, OperationInputDefinition operationInputDefinition,
+ PropertyDefinition serviceProperty) {
+ Map<String, List<String>> getProperty = new HashMap<>();
+ List<String> getPropertyValues = new ArrayList<>();
+ getPropertyValues.add(componentName);
+ getPropertyValues.add(serviceProperty.getName());
+ getProperty.put(ToscaFunctions.GET_PROPERTY.getFunctionName(), getPropertyValues);
+ operationInputDefinition.setSourceProperty(serviceProperty.getUniqueId());
+ operation.getInputs().delete(operationInputDefinition);
+ operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_PROPERTY, getPropertyValues);
+ operationInputDefinition.setValue((new Gson()).toJson(getProperty));
+ operation.getInputs().add(operationInputDefinition);
+ }
+
+ private void addOutputToInputValue(String componentName, String consumptionValue, Operation operation,
+ OperationInputDefinition operationInputDefinition) {
+ Map<String, List<String>> getOperationOutput = InterfaceOperationUtils.createMappedOutputDefaultValue(componentName, consumptionValue);
+ operation.getInputs().delete(operationInputDefinition);
+ operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_OPERATION_OUTPUT, getOperationOutput);
+ operationInputDefinition.setValue((new Gson()).toJson(getOperationOutput));
+ operation.getInputs().add(operationInputDefinition);
+ }
+
+ public Either<Operation, ResponseFormat> handleConsumptionStaticValue(String value, String type, Operation operation,
+ OperationInputDefinition operationInputDefinition, String model) {
+ boolean isInputTypeSimilarToOperation = isAssignedValueFromValidType(type, value);
+ if (!isInputTypeSimilarToOperation) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONSUMPTION_TYPE, type));
+ }
+ //Validate Constraint and Value
+ Either<Boolean, ResponseFormat> constraintValidationResponse = validateOperationInputConstraint(operationInputDefinition, value, type, model);
+ if (constraintValidationResponse.isRight()) {
+ return Either.right(constraintValidationResponse.right().value());
+ }
+ addStaticValueToInputOperation(value, operation, operationInputDefinition);
+ return Either.left(operation);
+ }
+
+ private Either<Boolean, ResponseFormat> validateOperationInputConstraint(OperationInputDefinition operationInputDefinition, String value,
+ String type, String model) {
+ ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty();
+ propertyDefinition.setType(operationInputDefinition.getParentPropertyType());
+ InputDefinition inputDefinition = new InputDefinition();
+ inputDefinition.setDefaultValue(value);
+ inputDefinition.setInputPath(operationInputDefinition.getSubPropertyInputPath());
+ inputDefinition.setType(type);
+ if (Objects.nonNull(operationInputDefinition.getParentPropertyType())) {
+ inputDefinition.setProperties(Collections.singletonList(propertyDefinition));
+ }
+ return new PropertyValueConstraintValidationUtil().validatePropertyConstraints(Collections.singletonList(inputDefinition),
+ applicationDataTypeCache, model);
+ }
+
+ private void addStaticValueToInputOperation(String value, Operation operation, OperationInputDefinition operationInputDefinition) {
+ operation.getInputs().delete(operationInputDefinition);
+ operationInputDefinition.setSource(STATIC.getSource());
+ operationInputDefinition.setSourceProperty(null);
+ operationInputDefinition.setValue(value);
+ operation.getInputs().add(operationInputDefinition);
+ }
+
+ private Either<Operation, ResponseFormat> handleConsumptionInputValue(String inputId, Service service, Operation operation,
+ OperationInputDefinition operationInputDefinition) {
+ List<InputDefinition> serviceInputs = service.getInputs();
+ Optional<InputDefinition> inputForValue = serviceInputs.stream().filter(input -> input.getUniqueId().contains(inputId)).findAny();
+ if (inputForValue.isPresent()) {
+ boolean isInputTypeSimilarToOperation = isAssignedValueFromValidType(operationInputDefinition.getType(), inputForValue.get());
+ if (!isInputTypeSimilarToOperation) {
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
+ }
+ addGetInputValueToOperationInput(operation, operationInputDefinition, inputForValue.get());
+ }
+ return Either.left(operation);
+ }
+
+ private void addGetInputValueToOperationInput(Operation operation, OperationInputDefinition operationInputDefinition,
+ InputDefinition inputForValue) {
+ operation.getInputs().delete(operationInputDefinition);
+ Map<String, String> getInputMap = new HashMap<>();
+ getInputMap.put(ToscaFunctions.GET_INPUT.getFunctionName(), inputForValue.getName());
+ operationInputDefinition.setSourceProperty(inputForValue.getUniqueId());
+ operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_INPUT, getInputMap);
+ operationInputDefinition.setValue(new Gson().toJson(getInputMap));
+ operation.getInputs().add(operationInputDefinition);