No properties found when trying to add a node filter to a VF
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / validation / NodeFilterValidator.java
index 9716dfa..f75abf7 100644 (file)
 
 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<String> comparableTypes = ImmutableSet.of(ToscaPropertyType.STRING.getType(),
-        ToscaPropertyType.INTEGER.getType(), ToscaPropertyType.FLOAT.getType());
-    public static final Set<String> schemableTypes =
-        ImmutableSet.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType());
-    public static final Set<String> 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<String> TYPES_WITH_SCHEMA = Set.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType());
+    private static final Set<String> 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<? extends ToscaPropertyData> 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<Boolean, ResponseFormat> validateComponentInstanceExist(final Component component,
-                                                                          final String componentInstanceId) {
+    public Either<Boolean, ResponseFormat> 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<Boolean, ResponseFormat> getErrorResponse(ActionStatus actionStatus, String... variables) {
-        ResponseFormat errorResponse = ResponseFormatManager.getInstance().getResponseFormat(actionStatus, variables);
-        return Either.right(errorResponse);
+    public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId,
+                                                          final List<FilterConstraintDto> filterConstraint) {
+        if (CollectionUtils.isEmpty(filterConstraint)) {
+            return Either.left(true);
+        }
+        for (final FilterConstraintDto filterConstraintDto : filterConstraint) {
+            final Either<Boolean, ResponseFormat> validationEither =
+                validateFilter(parentComponent, componentInstanceId, filterConstraintDto);
+            if (validationEither.isRight()) {
+                return validationEither;
+            }
+        }
+        return Either.left(true);
     }
 
-    public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent,
-                                                          final String componentInstanceId,
-                                                          final List<String> 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<Boolean, ResponseFormat> booleanResponseFormatEither =
-                            validatePropertyConstraint(parentComponent, componentInstanceId, constraint);
-                        if (booleanResponseFormatEither.isRight()) {
-                            return booleanResponseFormatEither;
-                        }
-                    } else if (ConstraintConvertor.STATIC_CONSTRAINT.equals(constraint.getSourceType())) {
-                        final Either<Boolean, ResponseFormat> booleanResponseFormatEither =
-                            validateStaticValueAndOperator(parentComponent, componentInstanceId, constraint);
-                        if (booleanResponseFormatEither.isRight()) {
-                            return booleanResponseFormatEither;
-                        }
-                    }
+    public Either<Boolean, ResponseFormat> 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<Boolean, ResponseFormat> validatePropertyConstraint(final Component parentComponent,
-                                                                       final String componentInstanceId,
-                                                                       final UIConstraint uiConstraint) {
+    private Either<Boolean, ResponseFormat> validatePropertyConstraint(final Component parentComponent, final String componentInstanceId,
+                                                                       final FilterConstraintDto filterConstraint, final String capabilityName) {
         String source = SOURCE;
-        final Optional<ComponentInstance> optionalComponentInstance;
-
-        final List<PropertyDefinition> propertyDefinitions = parentComponent.getProperties();
-        List<? extends PropertyDefinition> 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<ComponentInstanceProperty> componentInstanceProperties =
-                    parentComponent.getComponentInstancesProperties()
-                        .get(optionalComponentInstance.get().getUniqueId());
-                sourcePropertyDefinition =
-                    componentInstanceProperties == null ? new ArrayList<>() : componentInstanceProperties;
+        ResponseFormat responseFormat = null;
+        List<ToscaGetFunctionDataDefinition> toscaGetFunctionDataDefinitionList = new ArrayList<>();
+        final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null);
+        if (toscaGetFunction == null || !(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) {
+            final List<ToscaGetFunctionDataDefinition> 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<? extends PropertyDefinition> sourceSelectedProperty = sourcePropertyDefinition.stream()
-                .filter(property -> uiConstraint
-                    .getValue()
-                    .equals(property.getName()))
-                .findFirst();
+            final Optional<? extends ToscaPropertyData> sourceSelectedProperty =
+                findPropertyFromGetFunction(parentComponent, _toscaGetFunction);
+            if (sourceSelectedProperty.isPresent()) {
+                Optional<? extends PropertyDefinition> targetComponentInstanceProperty =
+                    getInstanceProperties(parentComponent, componentInstanceId, capabilityName, filterConstraint);
 
-            final Optional<? extends PropertyDefinition> 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<? extends ToscaPropertyData> findPropertyFromGetFunction(final Component parentComponent,
+                                                                              final ToscaGetFunctionDataDefinition toscaGetFunction) {
+        List<? extends ToscaPropertyData> sourcePropertyDefinitions;
+        if (PropertySource.SELF == toscaGetFunction.getPropertySource()) {
+            sourcePropertyDefinitions = getSelfPropertyFromGetFunction(parentComponent, toscaGetFunction);
+        } else {
+            sourcePropertyDefinitions = getInstancePropertiesBasedOnGetFunctionSource(parentComponent, toscaGetFunction);
+        }
+        final List<String> propertyPath = toscaGetFunction.getPropertyPathFromSource();
+        final Optional<? extends ToscaPropertyData> sourceProperty = sourcePropertyDefinitions.stream()
+            .filter(propertyDefinition -> propertyDefinition.getName().equals(propertyPath.get(0))).findFirst();
+        if (sourceProperty.isEmpty() || propertyPath.size() == 1) {
+            return sourceProperty;
+        }
+        final Either<Map<String, DataTypeDefinition>, 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<? extends ToscaPropertyData> 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<? extends ToscaPropertyData> 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<PropertyDefinition> findSubProperty(final List<String> propertyPath, final String parentPropertyType,
+                                                         final Map<String, DataTypeDefinition> 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<? extends PropertyDefinition> 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<ComponentInstance> componentInstanceOptional = parentComponent.getComponentInstances().stream()
+                .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId)).findAny();
+            if (componentInstanceOptional.isPresent()) {
+                for (final List<CapabilityDefinition> listOfCaps : componentInstanceOptional.get().getCapabilities().values()) {
+                    final Optional<CapabilityDefinition> 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<Boolean, ResponseFormat> validateInputConstraint(final Component parentComponent, final String componentInstanceId,
+                                                                    final FilterConstraintDto filterConstraint) {
+        final List<InputDefinition> 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<String> propertyPathFromSource = getFunction.getPropertyPathFromSource();
+            Optional<? extends PropertyDefinition> 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<Map<String, DataTypeDefinition>, 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<? extends PropertyDefinition> 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<Boolean, ResponseFormat> validatePropertyData(UIConstraint uiConstraint,
-                                                                 Optional<? extends PropertyDefinition> sourceSelectedProperty,
-                                                                 Optional<? extends PropertyDefinition> 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 <T extends ToscaPropertyData> 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<Boolean, ResponseFormat> validateStaticValueAndOperator(
-        final Component parentComponent,
-        final String componentInstanceId, final UIConstraint uiConstraint) {
-        if (!(Objects.nonNull(uiConstraint) && uiConstraint.getValue() instanceof String)) {
-            return Either.left(false);
+    private Either<Boolean, ResponseFormat> 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> 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<ComponentInstance> 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<Boolean, ResponseFormat> 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<Boolean, ResponseFormat> validateStaticValueAndOperatorOfCapabilityProperties(final Component parentComponent,
+                                                                                                 final String componentInstanceId,
+                                                                                                 final FilterConstraintDto filterConstraint) {
+        ComponentInstanceProperty componentInstanceProperty = null;
+        final Optional<ComponentInstance> optionalComponentInstances = parentComponent.getComponentInstances().stream()
+            .filter(componentInstance -> componentInstanceId.equalsIgnoreCase(componentInstance.getUniqueId())).findFirst();
+        if (optionalComponentInstances.isPresent()) {
+            final Optional<List<CapabilityDefinition>> 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<Boolean, ResponseFormat> isValidValueCheck(String type, String value, String propertyName) {
+    private Optional<ComponentInstanceProperty> 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<Boolean, ResponseFormat> isValidValueCheck(final String type, final String schemaType, final String model,
+                                                              final Object value, final String propertyName) {
+        final Either<Map<String, DataTypeDefinition>, 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<String, DataTypeDefinition> 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<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component,
+                                                                      final List<FilterConstraintDto> filterConstraintList) {
+        if (CollectionUtils.isEmpty(filterConstraintList)) {
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT));
+        }
+        for (final FilterConstraintDto filterConstraintDto : filterConstraintList) {
+            final Either<Boolean, ResponseFormat> validationEither = validateSubstitutionFilter(component, filterConstraintDto);
+            if (validationEither.isRight()) {
+                return validationEither;
+            }
+        }
+        return Either.left(true);
+    }
 
-}
+    public Either<Boolean, ResponseFormat> 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<Boolean, ResponseFormat> 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<? extends PropertyDefinition> 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<? extends ToscaPropertyData> 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 "";
+        }
+    }
+
+}