X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=catalog-be%2Fsrc%2Fmain%2Fjava%2Forg%2Fopenecomp%2Fsdc%2Fbe%2Fcomponents%2Fvalidation%2FNodeFilterValidator.java;h=f75abf73a163fc813e227a25cad80acfc74c1e8d;hb=0d9d05e705a6fbc9c4370fdd3a8ad543d04f8210;hp=9716dfae230cc0c327aebf5ba257fa1f3e5d2792;hpb=bdeb28f273da2494d7eeabbb5329222dfd168e3b;p=sdc.git diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java index 9716dfae23..f75abf73a1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java @@ -20,233 +20,668 @@ package org.openecomp.sdc.be.components.validation; -import com.google.common.collect.ImmutableSet; +import com.google.gson.Gson; import fj.data.Either; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.List; -import java.util.Objects; +import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.openecomp.sdc.be.components.impl.ResponseFormatManager; -import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; +import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; -import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.ConstraintType; +import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.ToscaPropertyData; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; +import org.openecomp.sdc.be.model.dto.FilterConstraintDto; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; -import org.openecomp.sdc.be.ui.model.UIConstraint; +import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter; +import org.openecomp.sdc.be.model.validation.FilterConstraintValidator; import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.util.CollectionUtils; @org.springframework.stereotype.Component("NodeFilterValidator") public class NodeFilterValidator { - private static final String SOURCE = "Source"; - public static final Set comparableTypes = ImmutableSet.of(ToscaPropertyType.STRING.getType(), - ToscaPropertyType.INTEGER.getType(), ToscaPropertyType.FLOAT.getType()); - public static final Set schemableTypes = - ImmutableSet.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType()); - public static final Set comparableConstraintsOperators = - ImmutableSet.of(ConstraintConvertor.GREATER_THAN_OPERATOR, ConstraintConvertor.LESS_THAN_OPERATOR); - - protected final ToscaOperationFacade toscaOperationFacade; - protected final ComponentsUtils componentsUtils; - private static final Logger LOGGER = LoggerFactory.getLogger(NodeFilterValidator.class); + private static final String SOURCE = "Source"; + private static final String TARGET = "Target"; + private static final String INPUT_NOT_FOUND_LOG = "Input '{}' not found in parent component '{}', unique id '{}'"; + private static final Set TYPES_WITH_SCHEMA = Set.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType()); + private static final Set COMPARABLE_TYPES = Set.of( + ToscaPropertyType.SCALAR_UNIT_SIZE.getType(), + ToscaPropertyType.SCALAR_UNIT_TIME.getType(), + ToscaPropertyType.SCALAR_UNIT_BITRATE.getType(), + ToscaPropertyType.SCALAR_UNIT_FREQUENCY.getType(), + ToscaPropertyType.BOOLEAN.getType(), + ToscaPropertyType.STRING.getType(), + ToscaPropertyType.INTEGER.getType(), + ToscaPropertyType.FLOAT.getType()); + private final ComponentsUtils componentsUtils; + private final ApplicationDataTypeCache applicationDataTypeCache; + private final FilterConstraintValidator filterConstraintValidator; @Autowired - public NodeFilterValidator(final ToscaOperationFacade toscaOperationFacade, - final ComponentsUtils componentsUtils) { - this.toscaOperationFacade = toscaOperationFacade; + public NodeFilterValidator(final ComponentsUtils componentsUtils, final ApplicationDataTypeCache applicationDataTypeCache, + final FilterConstraintValidator filterConstraintValidator) { this.componentsUtils = componentsUtils; + this.applicationDataTypeCache = applicationDataTypeCache; + this.filterConstraintValidator = filterConstraintValidator; + } + + private static List getSelfPropertyFromGetFunction(final Component component, + final ToscaGetFunctionDataDefinition toscaGetFunction) { + switch (toscaGetFunction.getFunctionType()) { + case GET_INPUT: + if (component.getInputs() != null) { + return component.getInputs(); + } + break; + case GET_PROPERTY: + if (component.getProperties() != null) { + return component.getProperties(); + } + break; + case GET_ATTRIBUTE: + if (component.getAttributes() != null) { + return component.getAttributes(); + } + break; + } + return List.of(); } - public Either validateComponentInstanceExist(final Component component, - final String componentInstanceId) { + public Either validateComponentInstanceExist(final Component component, final String componentInstanceId) { if (component == null || StringUtils.isEmpty(componentInstanceId)) { - LOGGER.error("Input data cannot be empty"); - return getErrorResponse(ActionStatus.FILTER_NOT_FOUND); + LOGGER.error("Expecting a component and a component instance id, given was '{}' and '{}'", component, componentInstanceId); + final String componentName = component == null ? "?" : component.getName(); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, componentName, componentInstanceId)); } - if (CollectionUtils.isEmpty(component.getComponentInstances()) || - component.getComponentInstances().stream() - .noneMatch(ci -> ci.getUniqueId().equals(componentInstanceId))) { - LOGGER.error("Component Instance list is empty"); - return getErrorResponse(ActionStatus.FILTER_NOT_FOUND); + if (CollectionUtils.isEmpty(component.getComponentInstances()) || component.getComponentInstances().stream() + .noneMatch(ci -> ci.getUniqueId().equals(componentInstanceId))) { + LOGGER.error("Component '{}' node instance list is empty or component instance '{}' not found", + component.getUniqueId(), componentInstanceId); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, + component.getName(), componentInstanceId)); } return Either.left(Boolean.TRUE); } - private Either getErrorResponse(ActionStatus actionStatus, String... variables) { - ResponseFormat errorResponse = ResponseFormatManager.getInstance().getResponseFormat(actionStatus, variables); - return Either.right(errorResponse); + public Either validateFilter(final Component parentComponent, final String componentInstanceId, + final List filterConstraint) { + if (CollectionUtils.isEmpty(filterConstraint)) { + return Either.left(true); + } + for (final FilterConstraintDto filterConstraintDto : filterConstraint) { + final Either validationEither = + validateFilter(parentComponent, componentInstanceId, filterConstraintDto); + if (validationEither.isRight()) { + return validationEither; + } + } + return Either.left(true); } - public Either validateFilter(final Component parentComponent, - final String componentInstanceId, - final List uiConstraints, - final NodeFilterConstraintAction action) { - try { - if (NodeFilterConstraintAction.ADD == action || NodeFilterConstraintAction.UPDATE == action) { - for (final String uiConstraint : uiConstraints) { - final UIConstraint constraint = new ConstraintConvertor().convert(uiConstraint); - if (ConstraintConvertor.PROPERTY_CONSTRAINT.equals(constraint.getSourceType())) { - final Either booleanResponseFormatEither = - validatePropertyConstraint(parentComponent, componentInstanceId, constraint); - if (booleanResponseFormatEither.isRight()) { - return booleanResponseFormatEither; - } - } else if (ConstraintConvertor.STATIC_CONSTRAINT.equals(constraint.getSourceType())) { - final Either booleanResponseFormatEither = - validateStaticValueAndOperator(parentComponent, componentInstanceId, constraint); - if (booleanResponseFormatEither.isRight()) { - return booleanResponseFormatEither; - } - } + public Either validateFilter(final Component parentComponent, final String componentInstanceId, + final FilterConstraintDto filterConstraint) { + validateFilterConstraint(filterConstraint); + switch (filterConstraint.getValueType()) { + case STATIC: + if (filterConstraint.isCapabilityPropertyFilter()) { + return validateStaticValueAndOperatorOfCapabilityProperties(parentComponent, componentInstanceId, filterConstraint); + } else { + return validateStaticValueAndOperator(parentComponent, componentInstanceId, filterConstraint); } - } - } catch (final Exception e) { - LOGGER.debug("Provided constraint" + uiConstraints, e); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT)); + case GET_PROPERTY: + return validatePropertyConstraint(parentComponent, componentInstanceId, filterConstraint, filterConstraint.getCapabilityName()); + case GET_INPUT: + return validateInputConstraint(parentComponent, componentInstanceId, filterConstraint); + default: + return Either.left(true); } + } - return Either.left(true); + private void validateFilterConstraint(final FilterConstraintDto filterConstraint) { + filterConstraintValidator.validate(filterConstraint); } - private Either validatePropertyConstraint(final Component parentComponent, - final String componentInstanceId, - final UIConstraint uiConstraint) { + private Either validatePropertyConstraint(final Component parentComponent, final String componentInstanceId, + final FilterConstraintDto filterConstraint, final String capabilityName) { String source = SOURCE; - final Optional optionalComponentInstance; - - final List propertyDefinitions = parentComponent.getProperties(); - List sourcePropertyDefinition = - parentComponent.getName().equals(uiConstraint.getSourceName()) && - propertyDefinitions != null ? propertyDefinitions : Collections.emptyList(); - - if (sourcePropertyDefinition.isEmpty() && !parentComponent.getName().equals(uiConstraint.getSourceName())) { - optionalComponentInstance = parentComponent.getComponentInstances().stream() - .filter(componentInstance -> uiConstraint.getSourceName() - .equals(componentInstance - .getName())) - .findFirst(); - - if (optionalComponentInstance.isPresent()) { - final List componentInstanceProperties = - parentComponent.getComponentInstancesProperties() - .get(optionalComponentInstance.get().getUniqueId()); - sourcePropertyDefinition = - componentInstanceProperties == null ? new ArrayList<>() : componentInstanceProperties; + ResponseFormat responseFormat = null; + List toscaGetFunctionDataDefinitionList = new ArrayList<>(); + final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null); + if (toscaGetFunction == null || !(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) { + final List toscaGetFunctionList = filterConstraint.getAsListToscaGetFunction().orElse(null); + if (toscaGetFunctionList == null || toscaGetFunctionList.isEmpty() || !(filterConstraint.getValue() instanceof List)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR)); + } else { + toscaGetFunctionDataDefinitionList = toscaGetFunctionList; } + } else { + toscaGetFunctionDataDefinitionList.add(toscaGetFunction); } + Boolean allGood = true; + for (ToscaGetFunctionDataDefinition _toscaGetFunction : toscaGetFunctionDataDefinitionList) { - if (!CollectionUtils.isEmpty(sourcePropertyDefinition)) { - final Optional sourceSelectedProperty = sourcePropertyDefinition.stream() - .filter(property -> uiConstraint - .getValue() - .equals(property.getName())) - .findFirst(); + final Optional sourceSelectedProperty = + findPropertyFromGetFunction(parentComponent, _toscaGetFunction); + if (sourceSelectedProperty.isPresent()) { + Optional targetComponentInstanceProperty = + getInstanceProperties(parentComponent, componentInstanceId, capabilityName, filterConstraint); - final Optional targetComponentInstanceProperty = - parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream() - .filter(property -> uiConstraint.getServicePropertyName().equals(property.getName())) - .findFirst(); + source = targetComponentInstanceProperty.isEmpty() ? TARGET : SOURCE; + if (targetComponentInstanceProperty.isPresent()) { + responseFormat = + validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get(), + filterConstraint.getOperator().isLengthConstraint()); + if (responseFormat != null) { + allGood = false; + break; + } - source = !targetComponentInstanceProperty.isPresent() ? "Target" : SOURCE; - if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) { - return validatePropertyData(uiConstraint, sourceSelectedProperty, targetComponentInstanceProperty); + } else { + allGood = false; + final String missingProperty = + SOURCE.equals(source) ? filterConstraint.getValue().toString() : filterConstraint.getPropertyName(); + responseFormat = + componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, source, missingProperty); + break; + } + } else { + allGood = false; + final String missingProperty = + SOURCE.equals(source) ? filterConstraint.getValue().toString() : filterConstraint.getPropertyName(); + responseFormat = + componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, source, missingProperty); + break; + } + } + if (allGood) { + return Either.left(true); + } + return Either.right(responseFormat); + } + + private Optional findPropertyFromGetFunction(final Component parentComponent, + final ToscaGetFunctionDataDefinition toscaGetFunction) { + List sourcePropertyDefinitions; + if (PropertySource.SELF == toscaGetFunction.getPropertySource()) { + sourcePropertyDefinitions = getSelfPropertyFromGetFunction(parentComponent, toscaGetFunction); + } else { + sourcePropertyDefinitions = getInstancePropertiesBasedOnGetFunctionSource(parentComponent, toscaGetFunction); + } + final List propertyPath = toscaGetFunction.getPropertyPathFromSource(); + final Optional sourceProperty = sourcePropertyDefinitions.stream() + .filter(propertyDefinition -> propertyDefinition.getName().equals(propertyPath.get(0))).findFirst(); + if (sourceProperty.isEmpty() || propertyPath.size() == 1) { + return sourceProperty; + } + final Either, JanusGraphOperationStatus> allDataTypesEither = + applicationDataTypeCache.getAll(parentComponent.getModel()); + if (allDataTypesEither.isRight()) { + return Optional.empty(); + } + return findSubProperty(propertyPath.subList(1, propertyPath.size()), sourceProperty.get().getType(), allDataTypesEither.left().value()); + } + + private List getInstancePropertiesBasedOnGetFunctionSource(final Component parentComponent, + final ToscaGetFunctionDataDefinition toscaGetFunction) { + final ComponentInstance componentInstance = parentComponent.getComponentInstances().stream() + .filter(componentInstance1 -> componentInstance1.getName().equals(toscaGetFunction.getSourceName())) + .findFirst() + .orElse(null); + if (componentInstance == null) { + return List.of(); + } + final List instanceProperties; + switch (toscaGetFunction.getFunctionType()) { + case GET_PROPERTY: + instanceProperties = parentComponent.getComponentInstancesProperties().get(componentInstance.getUniqueId()); + break; + case GET_ATTRIBUTE: + instanceProperties = parentComponent.getComponentInstancesAttributes().get(componentInstance.getUniqueId()); + break; + default: + instanceProperties = List.of(); + } + if (instanceProperties == null) { + return List.of(); + } + return instanceProperties; + } + + private Optional findSubProperty(final List propertyPath, final String parentPropertyType, + final Map modelDataTypes) { + final DataTypeDefinition dataTypeDefinition = modelDataTypes.get(parentPropertyType); + if (CollectionUtils.isEmpty(dataTypeDefinition.getProperties())) { + return Optional.empty(); + } + final PropertyDefinition propertyDefinition = dataTypeDefinition.getProperties().stream() + .filter(propertyDefinition1 -> propertyDefinition1.getName().equals(propertyPath.get(0))).findFirst().orElse(null); + if (propertyDefinition == null) { + return Optional.empty(); + } + if (propertyPath.size() == 1) { + return Optional.of(propertyDefinition); + } + return findSubProperty(propertyPath.subList(1, propertyPath.size()), propertyDefinition.getType(), modelDataTypes); + } + + private Optional getInstanceProperties(final Component parentComponent, final String componentInstanceId, + final String capabilityName, final FilterConstraintDto filterConstraint) { + if (StringUtils.isEmpty(capabilityName)) { + OriginTypeEnum componentInstanceType = getComponentInstanceOriginType(parentComponent, componentInstanceId); + if (componentInstanceType == null) { + return Optional.empty(); + } + PropertyDefinition componentInstanceProperty = + getComponentInstanceProperty(componentInstanceType, parentComponent, componentInstanceId, filterConstraint); + if (componentInstanceProperty == null) { + throw new ByActionStatusComponentException(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()); + } + if (componentInstanceProperty instanceof ComponentInstanceInput) { + return parentComponent.getComponentInstancesInputs().get(componentInstanceId).stream() + .filter(property -> filterConstraint.getPropertyName().equals(property.getName())).findFirst(); + } + return parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream() + .filter(property -> filterConstraint.getPropertyName().equals(property.getName())).findFirst(); + } else { + final Optional componentInstanceOptional = parentComponent.getComponentInstances().stream() + .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId)).findAny(); + if (componentInstanceOptional.isPresent()) { + for (final List listOfCaps : componentInstanceOptional.get().getCapabilities().values()) { + final Optional capDef = listOfCaps.stream().filter(cap -> cap.getName().equals(capabilityName)).findAny(); + if (capDef.isPresent()) { + return capDef.get().getProperties().stream().filter(property -> filterConstraint.getPropertyName().equals(property.getName())) + .findFirst(); + } + } } } + return Optional.empty(); + } - final String missingProperty = - source.equals(SOURCE) ? uiConstraint.getValue().toString() : uiConstraint.getServicePropertyName(); + private Either validateInputConstraint(final Component parentComponent, final String componentInstanceId, + final FilterConstraintDto filterConstraint) { + final List sourceInputDefinition = parentComponent.getInputs(); + if (CollectionUtils.isEmpty(sourceInputDefinition)) { + LOGGER.debug("Parent component '{}', unique id '{}', does not have inputs", parentComponent.getName(), parentComponent.getUniqueId()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_DOES_NOT_HAVE_INPUTS, parentComponent.getName())); + } + if (!(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) { + if (filterConstraint.getValue() instanceof List) { + Optional optValid = ((List) filterConstraint.getValue()).stream().filter(filterConstraintValue -> + !(filterConstraintValue instanceof ToscaGetFunctionDataDefinition)).findAny(); + if (optValid.isPresent()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR)); + } + } else { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR)); + } + } + if (filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition) { + final ToscaGetFunctionDataDefinition getFunction = + (ToscaGetFunctionDataDefinition) filterConstraint.getValue(); + final List propertyPathFromSource = getFunction.getPropertyPathFromSource(); + Optional sourceSelectedProperty = + sourceInputDefinition.stream().filter(input -> input.getName().equals(propertyPathFromSource.get(0))) + .findFirst(); + if (sourceSelectedProperty.isEmpty()) { + LOGGER.debug(INPUT_NOT_FOUND_LOG, + propertyPathFromSource.get(0), parentComponent.getName(), parentComponent.getUniqueId()); + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INPUT_NOT_FOUND, + propertyPathFromSource.get(0), parentComponent.getName()) + ); + } + if (propertyPathFromSource.size() > 1) { + final Either, JanusGraphOperationStatus> allDataTypesEither = + applicationDataTypeCache.getAll(parentComponent.getModel()); + if (allDataTypesEither.isRight()) { + LOGGER.error("Could not load data types for model {}", parentComponent.getModel()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED, + parentComponent.getModel())); + } + sourceSelectedProperty = + findSubProperty(propertyPathFromSource.subList(1, propertyPathFromSource.size()), + sourceSelectedProperty.get().getType(), + allDataTypesEither.left().value()); + } + final Optional targetComponentInstanceProperty; + if (PropertyFilterTargetType.CAPABILITY.equals(filterConstraint.getTargetType())) { + final CapabilityDefinition capability = parentComponent.getComponentInstances().stream() + .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId)) + .map(componentInstance -> componentInstance.getCapabilities().values()) + .flatMap(Collection::stream) + .flatMap(Collection::stream) + .filter(capabilityDefinition -> capabilityDefinition.getName() + .equals(filterConstraint.getCapabilityName())) + .findFirst().orElse(null); + if (capability == null) { + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND_IN_COMPONENT, + filterConstraint.getCapabilityName(), parentComponent.getComponentType().getValue(), + parentComponent.getName()) + ); + } + targetComponentInstanceProperty = capability.getProperties().stream() + .filter(property -> filterConstraint.getPropertyName().equals(property.getName())) + .findFirst(); + } else { + targetComponentInstanceProperty = + parentComponent.getComponentInstancesProperties() + .get(componentInstanceId).stream() + .filter(property -> filterConstraint.getPropertyName().equals(property.getName())) + .findFirst(); + } + if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) { + final ResponseFormat responseFormat = + validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get(), + filterConstraint.getOperator().isLengthConstraint()); + if (responseFormat != null) { + return Either.right(responseFormat); + } + return Either.left(true); + } - return Either.right( - componentsUtils.getResponseFormat(ActionStatus.MAPPED_PROPERTY_NOT_FOUND, source, missingProperty)); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUTS_NOT_FOUND)); + } + return Either.left(true); } - private Either validatePropertyData(UIConstraint uiConstraint, - Optional sourceSelectedProperty, - Optional targetComponentInstanceProperty) { - if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) { - final PropertyDefinition sourcePropDefinition = sourceSelectedProperty.get(); - final String sourceType = sourcePropDefinition.getType(); - final PropertyDefinition targetPropDefinition = targetComponentInstanceProperty.get(); - final String targetType = targetPropDefinition.getType(); + private ResponseFormat validatePropertyData(final T sourcePropDefinition, + final T targetPropDefinition, + final boolean isLengthConstraint) { + final String sourceType = sourcePropDefinition.getType(); + final String targetType = targetPropDefinition.getType(); + if (!isLengthConstraint) { if (sourceType.equals(targetType)) { - if (schemableTypes.contains(sourceType)) { - final SchemaDefinition sourceSchemaDefinition = sourcePropDefinition.getSchema(); - final SchemaDefinition targetSchemaDefinition = targetPropDefinition.getSchema(); - if (!sourceSchemaDefinition.equals(targetSchemaDefinition)) { - return Either - .right(componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH, - uiConstraint.getServicePropertyName(), uiConstraint.getValue().toString())); + if (TYPES_WITH_SCHEMA.contains(sourceType)) { + final String sourceSchemaType = sourcePropDefinition.getSchemaType(); + final String targetSchemaType = targetPropDefinition.getSchemaType(); + if (sourceSchemaType != null && !sourceSchemaType.equals(targetSchemaType)) { + return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH, + targetPropDefinition.getName(), targetSchemaType, sourcePropDefinition.getName(), + sourceSchemaType); } } - return Either.left(Boolean.TRUE); + return null; } else { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH, - uiConstraint.getServicePropertyName(), uiConstraint.getValue().toString())); + if (null != ((PropertyDefinition) sourcePropDefinition).getSchemaProperty()) { + if (((PropertyDefinition) sourcePropDefinition).getSchemaProperty().getType().equals(targetType)) { + if (TYPES_WITH_SCHEMA.contains(((PropertyDefinition) sourcePropDefinition).getSchemaProperty().getType())) { + final String sourceSchemaType = sourcePropDefinition.getSchemaType(); + final String targetSchemaType = targetPropDefinition.getSchemaType(); + if (sourceSchemaType != null && !sourceSchemaType.equals(targetSchemaType)) { + return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH, + targetPropDefinition.getName(), targetSchemaType, sourcePropDefinition.getName(), + sourceSchemaType); + } + } + return null; + } + } } } else { - LOGGER.debug( - "Null value passed to `validatePropertyData` - sourceSelectedProperty: '{}' - targetComponentInstanceProperty: '{}'", - sourceSelectedProperty, targetComponentInstanceProperty); - return Either.right(componentsUtils - .getResponseFormat(ActionStatus.GENERAL_ERROR, uiConstraint.getServicePropertyName(), - uiConstraint.getValue().toString())); + if (sourceType.equalsIgnoreCase("integer")) { + if (TYPES_WITH_SCHEMA.contains(sourceType)) { + final String sourceSchemaType = sourcePropDefinition.getSchemaType(); + if (sourceSchemaType != null && !sourceSchemaType.equalsIgnoreCase("integer")) { + return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH, + targetPropDefinition.getName(), "integer", sourcePropDefinition.getName(), + sourceSchemaType); + } + } + return null; + } } + return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH, + sourcePropDefinition.getName(), sourcePropDefinition.getType(), targetPropDefinition.getName(), targetPropDefinition.getType()); } - private Either validateStaticValueAndOperator( - final Component parentComponent, - final String componentInstanceId, final UIConstraint uiConstraint) { - if (!(Objects.nonNull(uiConstraint) && uiConstraint.getValue() instanceof String)) { - return Either.left(false); + private Either validateStaticValueAndOperator(final Component parentComponent, final String componentInstanceId, + final FilterConstraintDto filterConstraint) { + OriginTypeEnum componentInstanceType = getComponentInstanceOriginType(parentComponent, componentInstanceId); + if (componentInstanceType == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, componentInstanceId)); + } + PropertyDefinition componentInstanceProperty = + getComponentInstanceProperty(componentInstanceType, parentComponent, componentInstanceId, filterConstraint); + if (componentInstanceProperty == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName())); + } + if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentInstanceProperty.getType()) + && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(), + filterConstraint.getOperator().getType())); + } + if (filterConstraint.getOperator().equals(ConstraintType.VALID_VALUES) || filterConstraint.getOperator().equals(ConstraintType.IN_RANGE)) { + return isValidValueCheck("list", componentInstanceProperty.getType(), parentComponent.getModel(), + filterConstraint.getValue(), filterConstraint.getPropertyName()); + } + if (filterConstraint.getOperator().isLengthConstraint() && componentInstanceProperty.getType().equals("list")) { + return Either.left(true); } - final Optional componentInstanceProperty = - parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream() - .filter(property -> uiConstraint.getServicePropertyName().equals(property.getName())) - .findFirst(); + return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(), + filterConstraint.getValue(), filterConstraint.getPropertyName()); + } - if (!componentInstanceProperty.isPresent()) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, - uiConstraint.getServicePropertyName())); + private PropertyDefinition getComponentInstanceProperty(OriginTypeEnum componentInstanceType, Component parentComponent, + String componentInstanceId, FilterConstraintDto filterConstraint) { + if (isInput(componentInstanceType)) { + return parentComponent.getComponentInstancesInputs() + .get(componentInstanceId).stream().filter(input -> filterConstraint.getPropertyName().equals(input.getName())) + .findFirst() + .orElse(null); } - if (comparableConstraintsOperators.contains(uiConstraint.getConstraintOperator()) && !comparableTypes.contains( - componentInstanceProperty.get().getType())) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, - uiConstraint.getServicePropertyName(), uiConstraint.getConstraintOperator())); + return parentComponent.getComponentInstancesProperties() + .get(componentInstanceId).stream().filter(property -> filterConstraint.getPropertyName().equals(property.getName())) + .findFirst() + .orElse(null); + } + + private OriginTypeEnum getComponentInstanceOriginType(Component parentComponent, String componentInstanceId) { + Optional componentInstanceOptional = parentComponent.getComponentInstanceById(componentInstanceId); + if (componentInstanceOptional.isPresent()) { + ComponentInstance componentInstance = componentInstanceOptional.get(); + return componentInstance.getOriginType(); } + return null; + } - return isValidValueCheck(componentInstanceProperty.get().getType(), String.valueOf(uiConstraint.getValue()), - uiConstraint.getServicePropertyName()); + private boolean isInput(OriginTypeEnum instanceType) { + return OriginTypeEnum.VF.equals(instanceType) || OriginTypeEnum.PNF.equals(instanceType) || OriginTypeEnum.CVFC.equals(instanceType) || + OriginTypeEnum.CR.equals(instanceType); + } + + private Either validateStaticSubstitutionFilter(final Component component, + final FilterConstraintDto filterConstraint) { + + final PropertyDefinition componentProperty = component.getProperties().stream() + .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst().orElse(null); + if (componentProperty == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName())); + } + if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentProperty.getType()) + && !COMPARABLE_TYPES.contains(componentProperty.getType())) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(), + filterConstraint.getOperator().getType())); + } + if (filterConstraint.getOperator().equals(ConstraintType.VALID_VALUES) || filterConstraint.getOperator().equals(ConstraintType.IN_RANGE)) { + return isValidValueCheck("list", componentProperty.getType(), component.getModel(), + filterConstraint.getValue(), filterConstraint.getPropertyName()); + } + return isValidValueCheck(componentProperty.getType(), componentProperty.getSchemaType(), component.getModel(), + filterConstraint.getValue(), filterConstraint.getPropertyName()); + } + + private Either validateStaticValueAndOperatorOfCapabilityProperties(final Component parentComponent, + final String componentInstanceId, + final FilterConstraintDto filterConstraint) { + ComponentInstanceProperty componentInstanceProperty = null; + final Optional optionalComponentInstances = parentComponent.getComponentInstances().stream() + .filter(componentInstance -> componentInstanceId.equalsIgnoreCase(componentInstance.getUniqueId())).findFirst(); + if (optionalComponentInstances.isPresent()) { + final Optional> optionalCapabilityDefinitionList = optionalComponentInstances.get().getCapabilities().values() + .stream().filter(capabilityDefinitions -> capabilityDefinitions.stream() + .allMatch(capabilityDefinition -> capabilityDefinition.getProperties() != null)).collect(Collectors.toList()).stream().filter( + capabilityDefinitions -> capabilityDefinitions.stream().allMatch( + capabilityDefinition -> capabilityDefinition.getProperties().stream().anyMatch( + componentInstanceProperty1 -> filterConstraint.getPropertyName() + .equalsIgnoreCase(componentInstanceProperty1.getName())))).findFirst(); + if (optionalCapabilityDefinitionList.isPresent() && !optionalCapabilityDefinitionList.get().isEmpty()) { + componentInstanceProperty = + getComponentInstanceProperty(optionalCapabilityDefinitionList.get().get(0), filterConstraint.getPropertyName()).orElse(null); + } + } + + if (componentInstanceProperty == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName())); + } + if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentInstanceProperty.getType()) + && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(), + filterConstraint.getOperator().getType())); + } + return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(), + filterConstraint.getValue(), filterConstraint.getPropertyName()); } - private Either isValidValueCheck(String type, String value, String propertyName) { + private Optional getComponentInstanceProperty(CapabilityDefinition capabilityDefinition, final String propertyName) { + return capabilityDefinition.getProperties().stream().filter(property -> property.getName().equals(propertyName)).findAny(); + } - ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type); - if (Objects.isNull(toscaPropertyType)) { + private Either isValidValueCheck(final String type, final String schemaType, final String model, + final Object value, final String propertyName) { + final Either, JanusGraphOperationStatus> allDataTypesEither = + applicationDataTypeCache.getAll(model); + if (allDataTypesEither.isRight()) { + LOGGER.error("Could not validate filter value. Could not load data types for model {}", model); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED, model)); + } + final Map modelDataTypesMap = allDataTypesEither.left().value(); + final ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type); + if (toscaPropertyType == null && !modelDataTypesMap.containsKey(type)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_PROPERTY_TYPE, type, propertyName)); + } + final String valueAsJsonString; + try { + valueAsJsonString = new Gson().toJson(value); + } catch (final Exception e) { + LOGGER.debug("Unsupported property filter value", e); return Either.right( - componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_PROPERTY_TYPE, type, propertyName)); + componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, String.valueOf(value))); } - if (toscaPropertyType.getValidator().isValid(value, null)) { - return Either.left(Boolean.TRUE); + if (toscaPropertyType != null) { + if (toscaPropertyType.getValidator().isValid(valueAsJsonString, schemaType, modelDataTypesMap)) { + return Either.left(true); + } + } else { + if (DataTypeValidatorConverter.getInstance().isValid(valueAsJsonString, modelDataTypesMap.get(type), modelDataTypesMap)) { + return Either.left(true); + } } - return Either.right( - componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, value)); + + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, valueAsJsonString)); } + public Either validateSubstitutionFilter(final Component component, + final List filterConstraintList) { + if (CollectionUtils.isEmpty(filterConstraintList)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT)); + } + for (final FilterConstraintDto filterConstraintDto : filterConstraintList) { + final Either validationEither = validateSubstitutionFilter(component, filterConstraintDto); + if (validationEither.isRight()) { + return validationEither; + } + } + return Either.left(true); + } -} + public Either validateSubstitutionFilter(final Component component, final FilterConstraintDto filterConstraint) { + validateFilterConstraint(filterConstraint); + switch (filterConstraint.getValueType()) { + case STATIC: + return validateStaticSubstitutionFilter(component, filterConstraint); + case GET_PROPERTY: + case GET_ATTRIBUTE: + case GET_INPUT: + return validateSubstitutionFilterGetFunctionConstraint(component, filterConstraint); + default: + return Either.left(true); + } + } + private Either validateSubstitutionFilterGetFunctionConstraint(final Component component, + final FilterConstraintDto filterConstraint) { + final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null); + if (toscaGetFunction == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR)); + } + + if (CollectionUtils.isEmpty(component.getProperties())) { + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction), + filterConstraint.getPropertyName()) + ); + } + + final Optional targetComponentProperty = component.getProperties().stream() + .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst(); + if (targetComponentProperty.isEmpty()) { + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction), + filterConstraint.getPropertyName()) + ); + } + + final Optional sourceSelectedProperty = findPropertyFromGetFunction(component, toscaGetFunction); + if (sourceSelectedProperty.isEmpty()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, SOURCE, getPropertyType(toscaGetFunction), + String.join("->", toscaGetFunction.getPropertyPathFromSource()))); + } + final ResponseFormat responseFormat = + validatePropertyData(sourceSelectedProperty.get(), targetComponentProperty.get(), + filterConstraint.getOperator().isLengthConstraint()); + if (responseFormat != null) { + return Either.right(responseFormat); + } + return Either.left(true); + } + + private String getPropertyType(final ToscaGetFunctionDataDefinition toscaGetFunction) { + switch (toscaGetFunction.getType()) { + case GET_INPUT: + return "input"; + case GET_PROPERTY: + return "property"; + case GET_ATTRIBUTE: + return "attribute"; + default: + return ""; + } + } + +}