From b43eb22f91ffdc1e2ba5d82b3dc1a2c4250d06e0 Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Wed, 18 May 2022 22:09:25 +0100 Subject: Support of get_property in property assignment Refactors the current way store a get_input function allowing to support different get functions (get_property in this case). The information stored allows recreating and correctly validating the get function. Fix get function schema validation, the schema was being ignored. Improve validation error status and messages. Improve tosca get function dialog. Change-Id: I5de5f96dfba3c7a0fbb458885af5528bea7835aa Issue-ID: SDC-4014 Signed-off-by: andre.schmid --- .../impl/ComponentInstanceBusinessLogic.java | 192 ++++++++++++++------- .../ToscaGetFunctionExceptionSupplier.java | 94 ++++++++++ 2 files changed, 228 insertions(+), 58 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java (limited to 'catalog-be/src/main/java') diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index 0b284226ee..1fa459da80 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -43,10 +43,12 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.onap.sdc.tosca.datatypes.model.PropertyType; import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; +import org.openecomp.sdc.be.components.impl.exceptions.ToscaGetFunctionExceptionSupplier; import org.openecomp.sdc.be.components.impl.instance.ComponentInstanceChangeOperationOrchestrator; import org.openecomp.sdc.be.components.impl.utils.DirectivesUtil; import org.openecomp.sdc.be.components.merge.instance.ComponentInstanceMergeDataBusinessLogic; @@ -69,9 +71,11 @@ import org.openecomp.sdc.be.datatypes.elements.GetPolicyValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; import org.openecomp.sdc.be.exception.BusinessException; @@ -167,14 +171,13 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { private static final String RESTRICTED_OPERATION_ON_COMPONENT = "Restricted operation for user: {} on component {}"; private static final String RESOURCE_INSTANCE = "resource instance"; private static final String SERVICE = "service"; - private static final String UPDATE_PROPERTY_CONTEXT = "UpdatePropertyValueOnComponentInstance"; - - private ComponentInstanceOperation componentInstanceOperation; - private ArtifactsBusinessLogic artifactBusinessLogic; - private ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL; - private ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator; - private ForwardingPathOperation forwardingPathOperation; - private NodeFilterOperation nodeFilterOperation; + + private final ComponentInstanceOperation componentInstanceOperation; + private final ArtifactsBusinessLogic artifactBusinessLogic; + private final ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL; + private final ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator; + private final ForwardingPathOperation forwardingPathOperation; + private final NodeFilterOperation nodeFilterOperation; @Autowired private CompositionBusinessLogic compositionBusinessLogic; @Autowired @@ -1957,7 +1960,11 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { ComponentInstanceProperty componentInstanceProperty = validatePropertyExistsOnComponent(property, containerComponent, foundResourceInstance); String propertyParentUniqueId = property.getParentUniqueId(); - Either updatedPropertyValue = updatePropertyObjectValue(property, false, containerComponent.getModel()); + if (property.isGetFunction()) { + validateToscaGetFunction(property, containerComponent); + property.setValue(property.getToscaGetFunction().generatePropertyValue()); + } + Either updatedPropertyValue = updatePropertyObjectValue(property, containerComponent.getModel()); if (updatedPropertyValue.isRight()) { log.error("Failed to update property object value of property: {}", property); @@ -2106,7 +2113,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { .get(foundResourceInstance.getUniqueId()); Optional instanceProperty = instanceProperties.stream().filter(p -> p.getName().equals(property.getName())) .findAny(); - if (!instanceProperty.isPresent()) { + if (instanceProperty.isEmpty()) { throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, property.getName()); } return instanceProperty.get(); @@ -2268,7 +2275,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return false; } - private Either updatePropertyObjectValue(T property, boolean isInput, final String model) { + private Either updatePropertyObjectValue(T property, final String model) { final Map allDataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, model); String innerType = null; String propertyType = property.getType(); @@ -2276,13 +2283,13 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { log.debug("The type of the property {} is {}", property.getUniqueId(), propertyType); if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { - SchemaDefinition def = property.getSchema(); - if (def == null) { + SchemaDefinition schema = property.getSchema(); + if (schema == null) { log.debug("Schema doesn't exists for property of type {}", type); return Either .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE))); } - PropertyDataDefinition propDef = def.getProperty(); + PropertyDataDefinition propDef = schema.getProperty(); if (propDef == null) { log.debug("Property in Schema Definition inside property of type {} doesn't exist", type); return Either @@ -2294,8 +2301,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { // Specific Update Logic String newValue = property.getValue(); - if (property.getToscaGetFunctionType() != null) { - validateToscaGetFunction(property); + if (property.hasGetFunction()) { return Either.left(newValue); } @@ -2313,14 +2319,12 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { newValue = object.toString(); } } - if (!isInput) { - ImmutablePair pair = propertyOperation - .validateAndUpdateRules(propertyType, ((ComponentInstanceProperty) property).getRules(), innerType, allDataTypes, true); - if (pair.getRight() != null && Boolean.FALSE.equals(pair.getRight())) { - BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType); - return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse( - DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)))); - } + ImmutablePair pair = propertyOperation + .validateAndUpdateRules(propertyType, ((ComponentInstanceProperty) property).getRules(), innerType, allDataTypes, true); + if (pair.getRight() != null && Boolean.FALSE.equals(pair.getRight())) { + BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse( + DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)))); } return Either.left(newValue); } @@ -2368,29 +2372,96 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return Either.left(newValue); } - private void validateToscaGetFunction(T property) { - if (property.getToscaGetFunctionType() == ToscaGetFunctionType.GET_INPUT) { - final List getInputValues = property.getGetInputValues(); - if (CollectionUtils.isEmpty(getInputValues)) { - log.debug("No input information provided. Cannot set get_input."); - throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT); - } - if (getInputValues.size() > 1) { - log.debug("More than one input provided. Cannot set get_input."); - throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT); - } - final GetInputValueDataDefinition getInputValueDataDefinition = getInputValues.get(0); + private void validateToscaGetFunction(T property, Component parentComponent) { + final ToscaGetFunctionDataDefinition toscaGetFunction = property.getToscaGetFunction(); + if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_INPUT) { + validateGetFunction(property, parentComponent.getInputs(), parentComponent.getModel()); + return; + } + if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_PROPERTY) { + validateGetFunction(property, parentComponent.getProperties(), parentComponent.getModel()); + return; + } - if (!property.getType().equals(getInputValueDataDefinition.getInputType())) { - log.debug("Input type '{}' diverges from the property type '{}'. Cannot set get_input.", - getInputValueDataDefinition.getInputType(), property.getType()); - throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT); + throw ToscaGetFunctionExceptionSupplier.functionNotSupported(toscaGetFunction.getFunctionType()).get(); + } + + private void validateGetFunction(final T property, + final List parentProperties, + final String model) { + final ToscaGetFunctionDataDefinition toscaGetFunction = property.getToscaGetFunction(); + if (CollectionUtils.isEmpty(parentProperties)) { + throw ToscaGetFunctionExceptionSupplier + .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource(), + toscaGetFunction.getFunctionType() + ).get(); + } + validateGetPropertySource(toscaGetFunction.getFunctionType(), toscaGetFunction.getPropertySource()); + final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId(); + T referredProperty = (T) parentProperties.stream() + .filter(property1 -> getFunctionPropertyUniqueId.equals(property1.getUniqueId())) + .findFirst() + .orElseThrow(ToscaGetFunctionExceptionSupplier + .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource() + , toscaGetFunction.getFunctionType()) + ); + if (toscaGetFunction.isSubProperty()) { + referredProperty = findSubProperty(referredProperty, toscaGetFunction, model); + } + + if (!property.getType().equals(referredProperty.getType())) { + throw ToscaGetFunctionExceptionSupplier + .propertyTypeDiverge(toscaGetFunction.getFunctionType(), referredProperty.getType(), property.getType()).get(); + } + if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) { + throw ToscaGetFunctionExceptionSupplier + .propertySchemaDiverge(toscaGetFunction.getFunctionType(), referredProperty.getSchemaType(), property.getSchemaType()).get(); + } + } + + private T findSubProperty(final T referredProperty, final ToscaGetFunctionDataDefinition toscaGetFunction, + final String model) { + final Map dataTypeMap = loadDataTypes(model); + final List propertyPathFromSource = toscaGetFunction.getPropertyPathFromSource(); + DataTypeDefinition dataType = dataTypeMap.get(referredProperty.getType()); + if (dataType == null) { + throw ToscaGetFunctionExceptionSupplier + .propertyDataTypeNotFound(propertyPathFromSource.get(0), referredProperty.getType(), toscaGetFunction.getFunctionType()).get(); + } + T foundProperty = referredProperty; + for (int i = 1; i < propertyPathFromSource.size(); i++) { + final String currentPropertyName = propertyPathFromSource.get(i); + foundProperty = (T) dataType.getProperties().stream() + .filter(propertyDefinition -> currentPropertyName.equals(propertyDefinition.getName())).findFirst() + .orElseThrow( + ToscaGetFunctionExceptionSupplier + .propertyNotFoundOnTarget(propertyPathFromSource.subList(0, i), toscaGetFunction.getPropertySource(), + toscaGetFunction.getFunctionType()) + ); + dataType = dataTypeMap.get(foundProperty.getType()); + if (dataType == null) { + throw ToscaGetFunctionExceptionSupplier + .propertyDataTypeNotFound(propertyPathFromSource.subList(0, i), foundProperty.getType(), + toscaGetFunction.getFunctionType()).get(); } - return; } + return foundProperty; + } + + private Map loadDataTypes(String model) { + final Either, JanusGraphOperationStatus> dataTypeEither = + applicationDataTypeCache.getAll(model); + if (dataTypeEither.isRight()) { + throw ToscaGetFunctionExceptionSupplier.couldNotLoadDataTypes(model).get(); + } + return dataTypeEither.left().value(); + } - throw new ByActionStatusComponentException(ActionStatus.NOT_SUPPORTED, - "Tosca function " + property.getToscaGetFunctionType().getToscaGetFunctionName()); + private void validateGetPropertySource(final ToscaGetFunctionType functionType, final PropertySource propertySource) { + if (propertySource != PropertySource.SELF) { + throw ToscaGetFunctionExceptionSupplier + .targetSourceNotSupported(functionType, propertySource).get(); + } } private ResponseFormat updateInputOnContainerComponent(ComponentInstanceInput input, String newValue, Component containerComponent, @@ -3054,22 +3125,18 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return ComponentValidations.validateNameIsUniqueInComponent(oldComponentInstance.getName(), newInstanceName, containerComponent); } - private Either getResourceInstanceById(Component containerComponent, String instanceId) { - Either result = Either.right(StorageOperationStatus.NOT_FOUND); - List instances = containerComponent.getComponentInstances(); - Optional foundInstance = Optional.empty(); - if (!CollectionUtils.isEmpty(instances)) { - if (result.isRight()) { - foundInstance = instances.stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst(); - if (!foundInstance.isPresent()) { - result = Either.right(StorageOperationStatus.NOT_FOUND); - } - } - if (result.isRight() && foundInstance.isPresent()) { - result = Either.left(foundInstance.get()); - } + private Either getResourceInstanceById(final Component containerComponent, final String instanceId) { + final List instances = containerComponent.getComponentInstances(); + if (CollectionUtils.isEmpty(instances)) { + return Either.right(StorageOperationStatus.NOT_FOUND); } - return result; + + final Optional foundInstance = instances.stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst(); + if (foundInstance.isEmpty()) { + return Either.right(StorageOperationStatus.NOT_FOUND); + } + + return Either.left(foundInstance.get()); } private ComponentInstance buildComponentInstance(ComponentInstance resourceInstanceForUpdate, ComponentInstance origInstanceForUpdate) { @@ -3726,4 +3793,13 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { final User user = userValidations.validateUserExists(userId); userValidations.validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN)); } + + public void setCompositionBusinessLogic(CompositionBusinessLogic compositionBusinessLogic) { + this.compositionBusinessLogic = compositionBusinessLogic; + } + + public void setContainerInstanceTypesData(ContainerInstanceTypesData containerInstanceTypesData) { + this.containerInstanceTypesData = containerInstanceTypesData; + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java new file mode 100644 index 0000000000..d54cb79ba5 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java @@ -0,0 +1,94 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl.exceptions; + +import java.util.List; +import java.util.function.Supplier; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; +import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ToscaGetFunctionExceptionSupplier { + + public static Supplier targetSourceNotSupported(final ToscaGetFunctionType toscaGetFunctionType, + final PropertySource propertySource) { + final String errorMsg = String.format("%s on %s", toscaGetFunctionType.getFunctionName(), propertySource.getName()); + return () -> new ByActionStatusComponentException(ActionStatus.NOT_SUPPORTED, errorMsg); + } + + public static Supplier propertyNotFoundOnTarget(final String propertyName, + final PropertySource propertySource, + final ToscaGetFunctionType functionType) { + return propertyNotFoundOnTarget(List.of(propertyName), propertySource, functionType); + } + + public static Supplier propertyNotFoundOnTarget(final List propertyPathFromSource, + final PropertySource propertySource, + final ToscaGetFunctionType functionType) { + return () -> new ByActionStatusComponentException(ActionStatus.TOSCA_GET_FUNCTION_PROPERTY_NOT_FOUND, functionType.getPropertyType(), + String.join("->", propertyPathFromSource), propertySource.getName()); + } + + public static Supplier propertyDataTypeNotFound(final String propertyName, + final String dataType, + final ToscaGetFunctionType functionType) { + return propertyDataTypeNotFound(List.of(propertyName), dataType, functionType); + } + + public static Supplier propertyDataTypeNotFound(final List propertyPathFromSource, + final String dataType, + final ToscaGetFunctionType functionType) { + return () -> new ByActionStatusComponentException( + ActionStatus.TOSCA_GET_FUNCTION_PROPERTY_DATA_TYPE_NOT_FOUND, + functionType.getPropertyType(), String.join("->", propertyPathFromSource), dataType + ); + } + + public static Supplier couldNotLoadDataTypes(final String model) { + return () -> new ByActionStatusComponentException(ActionStatus.DATA_TYPES_NOT_LOADED, model); + } + + public static Supplier functionNotSupported(final ToscaGetFunctionType functionType) { + return () -> new ByActionStatusComponentException(ActionStatus.NOT_SUPPORTED, "Tosca function " + functionType.getFunctionName()); + } + + public static Supplier propertyTypeDiverge(final ToscaGetFunctionType functionType, + final String referredPropertyType, + final String propertyType) { + return () -> new ByActionStatusComponentException( + ActionStatus.TOSCA_GET_FUNCTION_TYPE_DIVERGE, + functionType.getFunctionName(), referredPropertyType, propertyType + ); + } + + public static Supplier propertySchemaDiverge(final ToscaGetFunctionType functionType, + final String referredPropertySchemaType, + final String propertySchemaType) { + return () -> new ByActionStatusComponentException( + ActionStatus.TOSCA_GET_FUNCTION_SCHEMA_DIVERGE, + functionType.getFunctionName(), referredPropertySchemaType, propertySchemaType + ); + } +} -- cgit 1.2.3-korg