From 7be04e3e3bdc899c52ffea1f6e11731771903f93 Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Mon, 25 Jul 2022 10:41:31 +0100 Subject: Centralize TOSCA function validation The validation happening in the component instance properties, should also be applied for the Group instance properties and Policy instance properties. Fixes some other problems related to the TOSCA function. Change-Id: I4b69da57a8444b78c72561f49146d32c6911482e Issue-ID: SDC-4114 Signed-off-by: andre.schmid --- .../sdc/be/config/CatalogModelSpringConfig.java | 1 + .../jsonjanusgraph/operations/GroupsOperation.java | 74 ++++------ .../be/model/operations/api/IGroupOperation.java | 21 ++- .../operations/impl/GroupInstanceOperation.java | 110 +++++++------- .../be/model/operations/impl/GroupOperation.java | 35 ++--- .../model/operations/impl/PropertyOperation.java | 162 ++++++++++++++++++++- .../be/model/tosca/converters/JsonConverter.java | 3 +- .../validators/DataTypeValidatorConverter.java | 4 +- .../model/validation/ToscaFunctionValidator.java | 41 ++++++ .../model/config/ModelOperationsSpringConfig.java | 12 +- .../config/ToscaValidationMockSpringConfig.java | 45 ++++++ .../test/resources/application-context-test.xml | 2 + 12 files changed, 373 insertions(+), 137 deletions(-) create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/validation/ToscaFunctionValidator.java create mode 100644 catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ToscaValidationMockSpringConfig.java (limited to 'catalog-model') diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/config/CatalogModelSpringConfig.java b/catalog-model/src/main/java/org/openecomp/sdc/be/config/CatalogModelSpringConfig.java index 19914380a6..eb26d59775 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/config/CatalogModelSpringConfig.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/config/CatalogModelSpringConfig.java @@ -29,6 +29,7 @@ import org.springframework.context.annotation.Configuration; // @formatter:off "org.openecomp.sdc.be.model.operations.impl", "org.openecomp.sdc.be.model.cache", + "org.openecomp.sdc.be.model.validation", "org.openecomp.sdc.be.client", "org.openecomp.sdc.be.model.jsonjanusgraph.utils", "org.openecomp.sdc.be.model.jsonjanusgraph.operations", diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/GroupsOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/GroupsOperation.java index d346d9364a..67eaae74ea 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/GroupsOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/GroupsOperation.java @@ -225,12 +225,7 @@ public class GroupsOperation extends BaseOperation { result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); } if (result == null) { - groups.forEach(gr -> { - updateVersion(promoteVersion, gr); - // String groupUUID = UniqueIdBuilder.generateUUID(); - - // gr.setGroupUUID(groupUUID); - }); + groups.forEach(gr -> updateVersion(promoteVersion, gr)); status = updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, groups, JsonPresentationFields.CI_INVARIANT_NAME); if (status != StorageOperationStatus.OK) { @@ -297,46 +292,36 @@ public class GroupsOperation extends BaseOperation { public Either, StorageOperationStatus> updateGroupPropertiesOnComponent(String componentId, GroupDefinition group, List newGroupProperties, PromoteVersionEnum promoteMinorVersion) { - Either, StorageOperationStatus> result = null; - Either getComponentVertex = null; - GraphVertex componentVertex = null; - getComponentVertex = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata); + Either getComponentVertex = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata); if (getComponentVertex.isRight()) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch component {}. Status is {} ", componentId); - result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); - } - if (result == null) { - componentVertex = getComponentVertex.left().value(); - //update - List properties = group.getProperties(); - newGroupProperties.forEach(np -> { - Optional currentProp = properties.stream().filter(p -> p.getName().equals(np.getName())).findAny(); - if (currentProp.isPresent()) { - currentProp.get().setValue(np.getValue()); - currentProp.get().setToscaFunction(np.getToscaFunction()); - } - }); - updateVersion(promoteMinorVersion, group); - StorageOperationStatus updateDataRes = updateToscaDataOfToscaElement(componentVertex, EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, group, - JsonPresentationFields.CI_INVARIANT_NAME); - if (updateDataRes != StorageOperationStatus.OK) { - log.debug("Failed to update properties for group {} error {}", group.getName(), updateDataRes); - result = Either.right(updateDataRes); - } + return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); } - if (result == null) { - componentVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis()); - Either updateRes = janusGraphDao.updateVertex(componentVertex); - if (updateRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the component {}. Status is {} ", componentId, - updateRes.right().value()); - result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updateRes.right().value())); + GraphVertex componentVertex = getComponentVertex.left().value(); + //update + List properties = group.getProperties(); + newGroupProperties.forEach(np -> { + Optional currentProp = properties.stream().filter(p -> p.getName().equals(np.getName())).findAny(); + if (currentProp.isPresent()) { + currentProp.get().setValue(np.getValue()); + currentProp.get().setToscaFunction(np.getToscaFunction()); } + }); + updateVersion(promoteMinorVersion, group); + StorageOperationStatus updateDataRes = updateToscaDataOfToscaElement(componentVertex, EdgeLabelEnum.GROUPS, VertexTypeEnum.GROUPS, group, + JsonPresentationFields.CI_INVARIANT_NAME); + if (updateDataRes != StorageOperationStatus.OK) { + log.debug("Failed to update properties for group {} error {}", group.getName(), updateDataRes); + return Either.right(updateDataRes); } - if (result == null) { - result = Either.left(newGroupProperties); + componentVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis()); + Either updateRes = janusGraphDao.updateVertex(componentVertex); + if (updateRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the component {}. Status is {} ", componentId, + updateRes.right().value()); + return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updateRes.right().value())); } - return result; + return Either.left(newGroupProperties); } public Either, StorageOperationStatus> updateGroupInstances(Component component, String instanceId, @@ -402,17 +387,10 @@ public class GroupsOperation extends BaseOperation { public Either updateGroupInstancePropertyValuesOnGraph(String componentId, String instanceId, GroupInstance oldGroupInstance, List newProperties) { - Either getComponentVertex = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.ParseMetadata); - if (getComponentVertex.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch component {}. Status is {} ", componentId); - return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value())); - } List propertiesOld = oldGroupInstance.getProperties(); newProperties.forEach(np -> { Optional prop = propertiesOld.stream().filter(p -> p.getName().equals(np.getName())).findFirst(); - if (prop.isPresent()) { - prop.get().setValue(np.getValue()); - } + prop.ifPresent(propertyDataDefinition -> propertyDataDefinition.setValue(np.getValue())); }); GroupInstanceDataDefinition groupInstanceDataDefinition = new GroupInstanceDataDefinition(oldGroupInstance); List pathKeys = new ArrayList<>(); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IGroupOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IGroupOperation.java index ccf7148f84..04d3a0bebe 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IGroupOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IGroupOperation.java @@ -23,19 +23,26 @@ import fj.data.Either; import java.util.List; import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.GroupProperty; import org.openecomp.sdc.be.resources.data.ArtifactData; public interface IGroupOperation { - public Either, StorageOperationStatus> dissociateAllGroupsFromArtifactOnGraph(String componentId, - NodeTypeEnum componentTypeEnum, - String artifactId); + Either, StorageOperationStatus> dissociateAllGroupsFromArtifactOnGraph(String componentId, NodeTypeEnum componentTypeEnum, + String artifactId); - public StorageOperationStatus dissociateAndAssociateGroupsFromArtifact(String componentId, NodeTypeEnum componentTypeEnum, String oldArtifactId, - ArtifactData newArtifact, boolean inTransaction); + StorageOperationStatus dissociateAndAssociateGroupsFromArtifact(String componentId, NodeTypeEnum componentTypeEnum, String oldArtifactId, + ArtifactData newArtifact, boolean inTransaction); - public boolean isGroupExist(String groupName, boolean inTransaction); + boolean isGroupExist(String groupName, boolean inTransaction); - public StorageOperationStatus validateAndUpdatePropertyValue(GroupProperty property); + /** + * Validates and updates the given property value based on the property type + * + * @param groupOwner the container component that owns the group instance that has the property + * @param property the group instance property to validate + * @return the status of the operation + */ + StorageOperationStatus validateAndUpdatePropertyValue(Component groupOwner, GroupProperty property); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupInstanceOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupInstanceOperation.java index c463af691c..67d9755808 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupInstanceOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupInstanceOperation.java @@ -56,6 +56,7 @@ import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator; import org.openecomp.sdc.be.resources.data.ArtifactData; import org.openecomp.sdc.be.resources.data.GroupInstanceData; import org.openecomp.sdc.be.resources.data.PropertyData; @@ -71,12 +72,20 @@ public class GroupInstanceOperation extends AbstractOperation implements IGroupI private static final String UPDATE_PROPERTY_VALUE_ON_COMPONENT_INSTANCE = "UpdatePropertyValueOnComponentInstance"; private static final String FAILED_TO_UPDATE_PROPERTY_VALUE_ON_INSTANCE_STATUS_IS = "Failed to update property value on instance. Status is "; private static final Logger log = Logger.getLogger(GroupInstanceOperation.class.getName()); + private final GroupOperation groupOperation; + private final PropertyOperation propertyOperation; + private final ToscaFunctionValidator toscaFunctionValidator; + private final ApplicationDataTypeCache applicationDataTypeCache; + @Autowired - GroupOperation groupOperation; - @Autowired - PropertyOperation propertyOperation; - @javax.annotation.Resource - private ApplicationDataTypeCache applicationDataTypeCache; + public GroupInstanceOperation(final GroupOperation groupOperation, final PropertyOperation propertyOperation, + final ToscaFunctionValidator toscaFunctionValidator, + final ApplicationDataTypeCache applicationDataTypeCache) { + this.groupOperation = groupOperation; + this.propertyOperation = propertyOperation; + this.toscaFunctionValidator = toscaFunctionValidator; + this.applicationDataTypeCache = applicationDataTypeCache; + } public Either, StorageOperationStatus> getAllGroupInstances(String parentId, NodeTypeEnum parentType) { Either, StorageOperationStatus> result = null; @@ -358,46 +367,47 @@ public class GroupInstanceOperation extends AbstractOperation implements IGroupI * * @return */ - public Either updatePropertyOfGroupInstance(ComponentInstanceProperty groupInstanceProerty, + public Either updatePropertyOfGroupInstance(ComponentInstanceProperty groupInstanceProperty, String groupInstanceId) { Wrapper errorWrapper = new Wrapper<>(); UpdateDataContainer updateDataContainer = new UpdateDataContainer<>(GraphEdgeLabels.PROPERTY_IMPL, (() -> PropertyData.class), (() -> PropertyValueData.class), NodeTypeEnum.Property, NodeTypeEnum.PropertyValue); - preUpdateElementOfResourceInstanceValidations(updateDataContainer, groupInstanceProerty, groupInstanceId, errorWrapper); + preUpdateElementOfResourceInstanceValidations(updateDataContainer, groupInstanceProperty, groupInstanceId, errorWrapper); if (!errorWrapper.isEmpty()) { return Either.right(errorWrapper.getInnerElement()); + } + + String value = groupInstanceProperty.getValue(); + // Specific Validation Logic + PropertyData propertyData = updateDataContainer.getDataWrapper().getInnerElement(); + PropertyDataDefinition propDataDef = propertyData.getPropertyDataDefinition(); + String propertyType = propDataDef.getType(); + final ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType); + log.debug("The type of the property {} is {}", propertyData.getUniqueId(), propertyType); + final Either innerTypeEither = propertyOperation.getInnerType(type, propDataDef::getSchema); + if (innerTypeEither.isRight()) { + return Either.right(innerTypeEither.right().value()); + } + // Specific Update Logic + Either, JanusGraphOperationStatus> allDataTypes = + applicationDataTypeCache.getAll(groupInstanceProperty.getModel()); + if (allDataTypes.isRight()) { + JanusGraphOperationStatus status = allDataTypes.right().value(); + BeEcompErrorManager.getInstance() + .logInternalFlowError(UPDATE_PROPERTY_VALUE_ON_COMPONENT_INSTANCE, FAILED_TO_UPDATE_PROPERTY_VALUE_ON_INSTANCE_STATUS_IS + status, + ErrorSeverity.ERROR); + return Either.right(status); + } + PropertyValueData propertyValueData = updateDataContainer.getValueDataWrapper().getInnerElement(); + if (propDataDef.isToscaFunction()) { + Either findResInstanceRes = janusGraphGenericDao + .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.GroupInstance), groupInstanceId, GroupInstanceData.class); + final GroupInstanceData groupInstanceData = findResInstanceRes.left().value(); + //TODO fix + toscaFunctionValidator.validate(propDataDef, null); + propertyValueData.setValue(propDataDef.getToscaFunction().getValue()); } else { - String value = groupInstanceProerty.getValue(); - // Specific Validation Logic - PropertyData propertyData = updateDataContainer.getDataWrapper().getInnerElement(); - String innerType = null; - PropertyDataDefinition propDataDef = propertyData.getPropertyDataDefinition(); - String propertyType = propDataDef.getType(); - ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType); - log.debug("The type of the property {} is {}", propertyData.getUniqueId(), propertyType); - if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { - SchemaDefinition def = propDataDef.getSchema(); - if (def == null) { - log.debug("Schema doesn't exists for property of type {}", type); - return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT); - } - PropertyDataDefinition propDef = def.getProperty(); - if (propDef == null) { - log.debug("Property in Schema Definition inside property of type {} doesn't exist", type); - return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT); - } - innerType = propDef.getType(); - } - // Specific Update Logic - Either, JanusGraphOperationStatus> allDataTypes = - applicationDataTypeCache.getAll(groupInstanceProerty.getModel()); - if (allDataTypes.isRight()) { - JanusGraphOperationStatus status = allDataTypes.right().value(); - BeEcompErrorManager.getInstance() - .logInternalFlowError(UPDATE_PROPERTY_VALUE_ON_COMPONENT_INSTANCE, FAILED_TO_UPDATE_PROPERTY_VALUE_ON_INSTANCE_STATUS_IS + status, - ErrorSeverity.ERROR); - return Either.right(status); - } + final String innerType = innerTypeEither.left().value(); Either isValid = propertyOperation .validateAndUpdatePropertyValue(propertyType, value, innerType, allDataTypes.left().value()); String newValue = value; @@ -412,25 +422,25 @@ public class GroupInstanceOperation extends AbstractOperation implements IGroupI newValue = object.toString(); } } - PropertyValueData propertyValueData = updateDataContainer.getValueDataWrapper().getInnerElement(); log.debug("Going to update property value from {} to {}", propertyValueData.getValue(), newValue); propertyValueData.setValue(newValue); ImmutablePair pair = propertyOperation - .validateAndUpdateRules(propertyType, groupInstanceProerty.getRules(), innerType, allDataTypes.left().value(), true); + .validateAndUpdateRules(propertyType, groupInstanceProperty.getRules(), innerType, allDataTypes.left().value(), true); if (pair.getRight() != null && !pair.getRight()) { BeEcompErrorManager.getInstance() - .logBeInvalidValueError("Add property value", pair.getLeft(), groupInstanceProerty.getName(), propertyType); + .logBeInvalidValueError("Add property value", pair.getLeft(), groupInstanceProperty.getName(), propertyType); return Either.right(JanusGraphOperationStatus.ILLEGAL_ARGUMENT); } - propertyOperation.updateRulesInPropertyValue(propertyValueData, groupInstanceProerty, groupInstanceId); - Either updateRes = janusGraphGenericDao - .updateNode(propertyValueData, PropertyValueData.class); - if (updateRes.isRight()) { - JanusGraphOperationStatus status = updateRes.right().value(); - return Either.right(status); - } else { - return Either.left(updateRes.left().value()); - } + } + + propertyOperation.updateRulesInPropertyValue(propertyValueData, groupInstanceProperty, groupInstanceId); + Either updateRes = janusGraphGenericDao + .updateNode(propertyValueData, PropertyValueData.class); + if (updateRes.isRight()) { + JanusGraphOperationStatus status = updateRes.right().value(); + return Either.right(status); + } else { + return Either.left(updateRes.left().value()); } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupOperation.java index a57f32d336..ce4696fa9f 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/GroupOperation.java @@ -34,9 +34,9 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge; import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; -import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao; import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels; import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; @@ -44,6 +44,7 @@ import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupProperty; @@ -62,9 +63,8 @@ import org.openecomp.sdc.be.resources.data.PropertyData; import org.openecomp.sdc.be.resources.data.PropertyValueData; import org.openecomp.sdc.be.resources.data.UniqueIdData; import org.openecomp.sdc.common.log.wrappers.Logger; -import org.springframework.stereotype.Component; -@Component +@org.springframework.stereotype.Component public class GroupOperation extends AbstractOperation implements IGroupOperation { private static final Logger log = Logger.getLogger(GroupOperation.class.getName()); @@ -481,33 +481,20 @@ public class GroupOperation extends AbstractOperation implements IGroupOperation return result; } - public StorageOperationStatus validateAndUpdatePropertyValue(GroupProperty property) { - StorageOperationStatus result = null; - String innerType = - property.getSchema() == null ? null : property.getSchema().getProperty() == null ? null : property.getSchema().getProperty().getType(); + public StorageOperationStatus validateAndUpdatePropertyValue(final Component groupOwner, final GroupProperty property) { Either, JanusGraphOperationStatus> allDataTypes = applicationDataTypeCache.getAll(property.getModel()); - Either isValid = null; if (allDataTypes.isRight()) { JanusGraphOperationStatus status = allDataTypes.right().value(); log.debug("Failed to fetch data types from cache. Status is {}. ", status); - result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status); - } - if (result == null) { - isValid = propertyOperation.validateAndUpdatePropertyValue(property.getType(), property.getValue(), innerType, - allDataTypes.left().value()); - if (isValid.isRight()) { - log.debug("Failed to validate property value {}. Status is {}. ", property.getValue(), StorageOperationStatus.INVALID_PROPERTY); - result = StorageOperationStatus.INVALID_PROPERTY; - } + return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status); } - if (result == null) { - if (isValid.left().value() != null) { - String validValue = String.valueOf(isValid.left().value()); - property.setValue(validValue); - } - result = StorageOperationStatus.OK; + + Either isValid = propertyOperation.validateAndUpdatePropertyValue(groupOwner, property, allDataTypes.left().value()); + if (isValid.isRight()) { + log.debug("Failed to validate property value {}. Status is {}. ", property.getValue(), StorageOperationStatus.INVALID_PROPERTY); + return StorageOperationStatus.INVALID_PROPERTY; } - return result; + return StorageOperationStatus.OK; } public StorageOperationStatus updateGroupProperties(org.openecomp.sdc.be.model.Component containerComponent, String groupId, diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java index 931d5993ea..b66f6c9433 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java @@ -76,11 +76,13 @@ import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyRule; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.IComplexDefaultValue; import org.openecomp.sdc.be.model.PropertyConstraint; import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator; import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation; import org.openecomp.sdc.be.model.operations.api.IPropertyOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; @@ -103,9 +105,8 @@ import org.openecomp.sdc.be.resources.data.ResourceMetadataData; import org.openecomp.sdc.be.resources.data.UniqueIdData; import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -@Component("property-operation") +@org.springframework.stereotype.Component("property-operation") public class PropertyOperation extends AbstractOperation implements IPropertyOperation { private static final String AFTER_RETRIEVING_DERIVED_FROM_NODE_OF_STATUS_IS = "After retrieving DERIVED_FROM node of {}. status is {}"; @@ -121,6 +122,7 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe private static final String UPDATE_DATA_TYPE = "UpdateDataType"; private static final Logger log = Logger.getLogger(PropertyOperation.class.getName()); private final DerivedFromOperation derivedFromOperation; + private ToscaFunctionValidator toscaFunctionValidator; private DataTypeOperation dataTypeOperation; @Autowired @@ -129,6 +131,11 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe this.derivedFromOperation = derivedFromOperation; } + @Autowired + public void setToscaFunctionValidator(final ToscaFunctionValidator toscaFunctionValidator) { + this.toscaFunctionValidator = toscaFunctionValidator; + } + //circular dependency DataTypeOperation->ModelOperation->ModelElementOperation->PropertyOperation @Autowired public void setDataTypeOperation(DataTypeOperation dataTypeOperation) { @@ -1645,7 +1652,7 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe public Either validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType, Map dataTypes) { log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value); - ToscaPropertyType type = getType(propertyType); + final ToscaPropertyType type = getType(propertyType); if (isValidate) { if (type == null) { DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType); @@ -1679,6 +1686,155 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe return validateAndUpdatePropertyValue(propertyType, value, true, innerType, dataTypes); } + public Either validateAndUpdatePropertyValue(final Component containerComponent, final PropertyDataDefinition property, + final Map dataTypes) { + if (property.isToscaFunction()) { + toscaFunctionValidator.validate(property, containerComponent); + property.setValue(property.getToscaFunction().getValue()); + return Either.left(property.getValue()); + } + Either checkInnerType = checkInnerType(property); + if (checkInnerType.isRight()) { + return Either.right(false); + } + final String innerType = checkInnerType.left().value(); + return validateAndUpdatePropertyValue(property.getType(), property.getValue(), true, innerType, dataTypes); + } + +// private void validateToscaGetFunction(T property, org.openecomp.sdc.be.model.Component parentComponent) { +// final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction(); +// validateGetToscaFunctionAttributes(toscaGetFunction); +// validateGetPropertySource(toscaGetFunction.getFunctionType(), toscaGetFunction.getPropertySource()); +// if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_INPUT) { +// validateGetFunction(property, parentComponent.getInputs(), parentComponent.getModel()); +// return; +// } +// if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_PROPERTY) { +// if (toscaGetFunction.getPropertySource() == PropertySource.SELF) { +// validateGetFunction(property, parentComponent.getProperties(), parentComponent.getModel()); +// } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) { +// final ComponentInstance componentInstance = +// parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId()) +// .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName())); +// validateGetFunction(property, componentInstance.getProperties(), parentComponent.getModel()); +// } +// +// return; +// } +// if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_ATTRIBUTE) { +// if (toscaGetFunction.getPropertySource() == PropertySource.SELF) { +// validateGetFunction(property, parentComponent.getAttributes(), parentComponent.getModel()); +// } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) { +// final ComponentInstance componentInstance = +// parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId()) +// .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName())); +// validateGetFunction(property, componentInstance.getAttributes(), parentComponent.getModel()); +// } +// +// return; +// } +// +// throw ToscaGetFunctionExceptionSupplier.functionNotSupported(toscaGetFunction.getFunctionType()).get(); +// } + +// private void validateGetFunction(final T property, +// final List parentProperties, +// final String model) { +// final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction(); +// if (CollectionUtils.isEmpty(parentProperties)) { +// throw ToscaGetFunctionExceptionSupplier +// .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource(), +// toscaGetFunction.getFunctionType() +// ).get(); +// } +// final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId(); +// ToscaPropertyData referredProperty = 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.getType(), referredProperty.getType(), property.getType()).get(); +// } +// if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) { +// throw ToscaGetFunctionExceptionSupplier +// .propertySchemaDiverge(toscaGetFunction.getType(), referredProperty.getSchemaType(), property.getSchemaType()).get(); +// } +// } + +// private void validateGetToscaFunctionAttributes(final ToscaGetFunctionDataDefinition toscaGetFunction) { +// if (toscaGetFunction.getFunctionType() == null) { +// throw ToscaGetFunctionExceptionSupplier.targetFunctionTypeNotFound().get(); +// } +// if (toscaGetFunction.getPropertySource() == null) { +// throw ToscaGetFunctionExceptionSupplier.targetPropertySourceNotFound(toscaGetFunction.getFunctionType()).get(); +// } +// if (CollectionUtils.isEmpty(toscaGetFunction.getPropertyPathFromSource())) { +// throw ToscaGetFunctionExceptionSupplier +// .targetSourcePathNotFound(toscaGetFunction.getFunctionType()).get(); +// } +// if (StringUtils.isEmpty(toscaGetFunction.getSourceName()) || StringUtils.isBlank(toscaGetFunction.getSourceName())) { +// throw ToscaGetFunctionExceptionSupplier.sourceNameNotFound(toscaGetFunction.getPropertySource()).get(); +// } +// if (StringUtils.isEmpty(toscaGetFunction.getSourceUniqueId()) || StringUtils.isBlank(toscaGetFunction.getSourceUniqueId())) { +// throw ToscaGetFunctionExceptionSupplier.sourceIdNotFound(toscaGetFunction.getPropertySource()).get(); +// } +// if (StringUtils.isEmpty(toscaGetFunction.getPropertyName()) || StringUtils.isBlank(toscaGetFunction.getPropertyName())) { +// throw ToscaGetFunctionExceptionSupplier.propertyNameNotFound(toscaGetFunction.getPropertySource()).get(); +// } +// if (StringUtils.isEmpty(toscaGetFunction.getPropertyUniqueId()) || StringUtils.isBlank(toscaGetFunction.getPropertyUniqueId())) { +// throw ToscaGetFunctionExceptionSupplier.propertyIdNotFound(toscaGetFunction.getPropertySource()).get(); +// } +// } + +// private void validateGetPropertySource(final ToscaGetFunctionType functionType, final PropertySource propertySource) { +// if (functionType == ToscaGetFunctionType.GET_INPUT && propertySource != PropertySource.SELF) { +// throw ToscaGetFunctionExceptionSupplier +// .targetSourceNotSupported(functionType, propertySource).get(); +// } +// if (functionType == ToscaGetFunctionType.GET_PROPERTY && !List.of(PropertySource.SELF, PropertySource.INSTANCE).contains(propertySource)) { +// throw ToscaGetFunctionExceptionSupplier +// .targetSourceNotSupported(functionType, propertySource).get(); +// } +// } + +// private ToscaPropertyData findSubProperty(final ToscaPropertyData 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(); +// } +// ToscaPropertyData foundProperty = referredProperty; +// for (int i = 1; i < propertyPathFromSource.size(); i++) { +// final String currentPropertyName = propertyPathFromSource.get(i); +// foundProperty = 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 foundProperty; +// } + public Either, StorageOperationStatus> getAllPropertiesRec(String uniqueId, NodeTypeEnum nodeType, Class clazz) { return this.findPropertiesOfNode(nodeType, uniqueId).right().bind(this::handleNotFoundProperties).left() diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/JsonConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/JsonConverter.java index d773f03e56..13a6302c5c 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/JsonConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/converters/JsonConverter.java @@ -31,7 +31,6 @@ import org.openecomp.sdc.common.util.GsonFactory; public class JsonConverter implements PropertyValueConverter { private static JsonConverter jsonConverter = new JsonConverter(); - private static JsonParser jsonParser = new JsonParser(); private static Gson gson = GsonFactory.getGson(); private JsonConverter() { @@ -46,7 +45,7 @@ public class JsonConverter implements PropertyValueConverter { StringReader reader = new StringReader(value); JsonReader jsonReader = new JsonReader(reader); jsonReader.setLenient(true); - JsonElement jsonElement = jsonParser.parse(jsonReader); + JsonElement jsonElement = JsonParser.parseReader(jsonReader); if (jsonElement.isJsonPrimitive()) { return value; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/DataTypeValidatorConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/DataTypeValidatorConverter.java index fb4e12c6a4..0a537a5445 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/DataTypeValidatorConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/validators/DataTypeValidatorConverter.java @@ -212,9 +212,9 @@ public class DataTypeValidatorConverter { if (value == null || value.isEmpty()) { return trueEmptyResult; } - JsonElement jsonElement = null; + final JsonElement jsonElement; try { - jsonElement = jsonParser.parse(value); + jsonElement = JsonParser.parseString(value); } catch (JsonSyntaxException e) { return falseResult; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/validation/ToscaFunctionValidator.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/validation/ToscaFunctionValidator.java new file mode 100644 index 0000000000..b667e6367a --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/validation/ToscaFunctionValidator.java @@ -0,0 +1,41 @@ +/* + * - + * ============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.model.validation; + +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.model.Component; + +/** + * Represents a validator for a property that has a TOSCA function value + */ +@org.springframework.stereotype.Component +public interface ToscaFunctionValidator { + + /** + * Validates the given property that has a TOSCA function value. Should throw a RuntimeException in case of failure. + * + * @param property the property with a tosca function to validate + * @param containerComponent the component that is the container for the instance that has the property + * @param a property data definition + */ + void validate(T property, Component containerComponent); +} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ModelOperationsSpringConfig.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ModelOperationsSpringConfig.java index 28e17b5075..f8bbd0aac0 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ModelOperationsSpringConfig.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ModelOperationsSpringConfig.java @@ -20,6 +20,9 @@ package org.openecomp.sdc.be.model.config; +import org.mockito.Mockito; +import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @@ -32,4 +35,11 @@ import org.springframework.context.annotation.PropertySource; "org.openecomp.sdc.be.model.jsonjanusgraph.config", "org.openecomp.sdc.be.model.operations.impl"}) @PropertySource("classpath:dao.properties") -public class ModelOperationsSpringConfig { } +public class ModelOperationsSpringConfig { + + @Bean + public ToscaFunctionValidator toscaFunctionValidator() { + return Mockito.mock(ToscaFunctionValidator.class); + } + +} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ToscaValidationMockSpringConfig.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ToscaValidationMockSpringConfig.java new file mode 100644 index 0000000000..ba834b1c1a --- /dev/null +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ToscaValidationMockSpringConfig.java @@ -0,0 +1,45 @@ +/* + * - + * ============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.model.config; + +import org.mockito.Mockito; +import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Configure a {@link ToscaFunctionValidator} mock as a Spring Bean for Spring tests + */ +@Configuration +public class ToscaValidationMockSpringConfig { + + /** + * Configures the {@link ToscaFunctionValidator} mock as Sprint Bean + * + * @return the {@link ToscaFunctionValidator} mock + */ + @Bean + public ToscaFunctionValidator toscaFunctionValidator() { + return Mockito.mock(ToscaFunctionValidator.class); + } + +} diff --git a/catalog-model/src/test/resources/application-context-test.xml b/catalog-model/src/test/resources/application-context-test.xml index 7f4ada2696..47c41bd62a 100644 --- a/catalog-model/src/test/resources/application-context-test.xml +++ b/catalog-model/src/test/resources/application-context-test.xml @@ -11,6 +11,8 @@ org.openecomp.sdc.be.dao.jsongraph, org.openecomp.sdc.be.model.cache, org.openecomp.sdc.be.client, + org.openecomp.sdc.be.model.validation, + org.openecomp.sdc.be.model.config, org.openecomp.sdc.be.dao.janusgraph, org.openecomp.sdc.be.dao.cassandra, org.openecomp.sdc.be.model.jsonjanusgraph.utils, -- cgit 1.2.3-korg