Support INDEX in node filter tosca functions 20/134720/4
authorfranciscovila <javier.paradela.vila@est.tech>
Tue, 30 May 2023 16:03:07 +0000 (17:03 +0100)
committerMichael Morris <michael.morris@est.tech>
Fri, 2 Jun 2023 14:29:33 +0000 (14:29 +0000)
Issue-ID: SDC-4517
Signed-off-by: franciscovila <javier.paradela.vila@est.tech>
Change-Id: I36e33821ef72c3375d9525513f2394b9b772c696

catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/NodeFilterValidatorTest.java
common-be/src/main/java/org/openecomp/sdc/be/utils/PropertyFilterConstraintDataDefinitionHelper.java
common-be/src/test/java/org/openecomp/sdc/be/utils/PropertyFilterConstraintDataDefinitionHelperTest.java
common-be/src/test/resources/nodeFilter/constraints/legacy-get_input-from-self.yaml [new file with mode: 0644]

index 30fe3dc..a0716fe 100644 (file)
@@ -415,6 +415,22 @@ public class NodeFilterValidator {
                 }
                 return null;
             }
+            else {
+                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 {
             if (sourceType.equalsIgnoreCase("integer")) {
index 67ecb7f..ef5f7a0 100644 (file)
@@ -27,6 +27,7 @@ import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
 import fj.data.Either;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -41,6 +42,7 @@ import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
@@ -52,6 +54,7 @@ import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.Service;
 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
@@ -139,7 +142,7 @@ class NodeFilterValidatorTest {
             FilterValueType.GET_PROPERTY,
             ConstraintType.EQUAL,
             PropertyFilterTargetType.PROPERTY,
-            createToscaGetFunction("test", PropertySource.INSTANCE, ToscaGetFunctionType.GET_PROPERTY, List.of("test2"))
+            createToscaGetFunction("test", PropertySource.INSTANCE, ToscaGetFunctionType.GET_PROPERTY, List.of("test2"), null)
         );
         Either<Boolean, ResponseFormat> actualValidationResult =
             nodeFilterValidator.validateSubstitutionFilter(service, Collections.singletonList(filterConstraint1));
@@ -150,7 +153,7 @@ class NodeFilterValidatorTest {
             FilterValueType.GET_PROPERTY,
             ConstraintType.EQUAL,
             PropertyFilterTargetType.PROPERTY,
-            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of("Prop1"))
+            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of("Prop1"), null)
         );
         actualValidationResult =
             nodeFilterValidator.validateSubstitutionFilter(service, Collections.singletonList(filterConstraint2));
@@ -199,6 +202,41 @@ class NodeFilterValidatorTest {
         assertTrue(actualValidationResult.isRight());
     }
 
+    @Test
+    void testValidateComponentFilterWithIndex() {
+        Service service = createService("string", "schema");
+        final var filterConstraint1 = buildFilterConstraintDto(
+            PROPERTY_NAME,
+            FilterValueType.GET_PROPERTY,
+            ConstraintType.EQUAL,
+            PropertyFilterTargetType.PROPERTY,
+            createToscaGetFunction("test", PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME, "alist"), List.of("1"))
+        );
+        Map<String, DataTypeDefinition> data = new HashMap<>();
+        DataTypeDefinition dataTypeDefinition = new DataTypeDefinition();
+        List<PropertyDefinition> properties = new ArrayList<>();
+        PropertyDefinition propertyDefinition = new PropertyDefinition();
+        propertyDefinition.setName("alist");
+        propertyDefinition.setType("list");
+
+        SchemaDefinition schemaDefinition = new SchemaDefinition();
+        PropertyDataDefinition schemaProperty = new PropertyDataDefinition();
+        schemaProperty.setType("string");
+        schemaDefinition.setProperty(schemaProperty);
+        propertyDefinition.setSchema(schemaDefinition);
+
+        properties.add(propertyDefinition);
+        dataTypeDefinition.setProperties(properties);
+
+        data.put("string", dataTypeDefinition);
+        Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes = Either.left(data);
+        when(applicationDataTypeCache.getAll(null)).thenReturn(allDataTypes);
+
+        Either<Boolean, ResponseFormat> actualValidationResult =
+            nodeFilterValidator.validateSubstitutionFilter(service, Collections.singletonList(filterConstraint1));
+        assertTrue(actualValidationResult.isLeft());
+    }
+
     @Test
     void testValidateNodeFilterStaticIncorrectOperatorProvidedBoolean() {
         Service service = createService(ToscaPropertyType.BOOLEAN.getType());
@@ -309,7 +347,7 @@ class NodeFilterValidatorTest {
     void testValidatePropertyConstraintBrotherSuccess() {
         Service service = createService(ToscaPropertyType.STRING.getType());
         final ToscaGetFunctionDataDefinition toscaGetFunction =
-            createToscaGetFunction(COMPONENT2_ID, PropertySource.INSTANCE, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME));
+            createToscaGetFunction(COMPONENT2_ID, PropertySource.INSTANCE, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME), null);
         final var filterConstraintDto = buildFilterConstraintDto(
             PROPERTY_NAME,
             FilterValueType.GET_PROPERTY,
@@ -328,7 +366,7 @@ class NodeFilterValidatorTest {
     void testValidatePropertyConstraintParentSuccess() {
         final var service = createService(ToscaPropertyType.STRING.getType());
         final ToscaGetFunctionDataDefinition toscaGetFunction =
-            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME));
+            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME), null);
         final var filterConstraintDto = buildFilterConstraintDto(
             PROPERTY_NAME,
             FilterValueType.GET_PROPERTY,
@@ -348,7 +386,7 @@ class NodeFilterValidatorTest {
         final Service service = createService(ToscaPropertyType.STRING.getType());
         service.getComponentInstancesProperties().get(COMPONENT2_ID).get(0).setType(ToscaPropertyType.INTEGER.getType());
         final ToscaGetFunctionDataDefinition toscaGetFunction =
-            createToscaGetFunction(COMPONENT2_ID, PropertySource.INSTANCE, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME));
+            createToscaGetFunction(COMPONENT2_ID, PropertySource.INSTANCE, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME), null);
         final var filterConstraintDto = buildFilterConstraintDto(
             PROPERTY_NAME,
             FilterValueType.GET_PROPERTY,
@@ -374,7 +412,7 @@ class NodeFilterValidatorTest {
         final Service service = createService(ToscaPropertyType.STRING.getType());
         service.getComponentInstancesProperties().get(COMPONENT1_ID).get(0).setType(ToscaPropertyType.INTEGER.getType());
         final ToscaGetFunctionDataDefinition toscaGetFunction =
-            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME));
+            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME), null);
         final var filterConstraintDto = buildFilterConstraintDto(
             PROPERTY_NAME,
             FilterValueType.GET_PROPERTY,
@@ -405,7 +443,7 @@ class NodeFilterValidatorTest {
             .thenReturn(expectedResponse);
 
         final ToscaGetFunctionDataDefinition toscaGetFunction =
-            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME));
+            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME), null);
         final var filterConstraintDto = buildFilterConstraintDto(
             PROPERTY_NAME,
             FilterValueType.GET_PROPERTY,
@@ -425,7 +463,7 @@ class NodeFilterValidatorTest {
         Service service = createService(ToscaPropertyType.STRING.getType());
         service.getComponentInstancesProperties().get(COMPONENT1_ID).get(0).setName("Prop2");
         final ToscaGetFunctionDataDefinition toscaGetFunction =
-            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME));
+            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME), null);
         final var filterConstraintDto = buildFilterConstraintDto(
             PROPERTY_NAME,
             FilterValueType.GET_PROPERTY,
@@ -446,13 +484,15 @@ class NodeFilterValidatorTest {
     protected static ToscaGetFunctionDataDefinition createToscaGetFunction(final String sourceName,
                                                                            final PropertySource propertySource,
                                                                            final ToscaGetFunctionType toscaGetFunctionType,
-                                                                           final List<String> propertyPathFromSource) {
+                                                                           final List<String> propertyPathFromSource,
+                                                                           final List<Object> toscaIndexList) {
         final var toscaGetFunction = new ToscaGetFunctionDataDefinition();
         toscaGetFunction.setFunctionType(toscaGetFunctionType);
         toscaGetFunction.setPropertyPathFromSource(propertyPathFromSource);
         toscaGetFunction.setSourceName(sourceName);
         toscaGetFunction.setPropertySource(propertySource);
         toscaGetFunction.setPropertyName(propertyPathFromSource.get(0));
+        toscaGetFunction.setToscaIndexList(toscaIndexList);
         return toscaGetFunction;
     }
 
@@ -467,7 +507,7 @@ class NodeFilterValidatorTest {
         service.getComponentInstancesProperties().get(COMPONENT1_ID).get(0).setSchema(schemaDefinition);
 
         final ToscaGetFunctionDataDefinition toscaGetFunction =
-            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME));
+            createToscaGetFunction(PARENT_SERVICE_ID, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, List.of(PROPERTY_NAME), null);
         final var filterConstraintDto = buildFilterConstraintDto(
             PROPERTY_NAME,
             FilterValueType.GET_PROPERTY,
index 63c6781..6377152 100644 (file)
 
 package org.openecomp.sdc.be.utils;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ToscaConcatFunction;
 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
@@ -39,7 +43,6 @@ import org.openecomp.sdc.be.datatypes.enums.FilterValueType;
 import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType;
 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
-import org.openecomp.sdc.exception.InvalidArgumentException;
 import org.yaml.snakeyaml.Yaml;
 
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
@@ -125,53 +128,104 @@ public class PropertyFilterConstraintDataDefinitionHelper {
 
     private static Optional<ToscaFunction> readLegacyGetPropertyConstraintValue(Map<?, ?> filterValueAsMap, Object toscaFunctionType,
                                                                                 ToscaFunctionType toscaFunctionType1) {
-        final var toscaGetFunction = new ToscaGetFunctionDataDefinition();
-        toscaGetFunction.setFunctionType(ToscaGetFunctionType.fromToscaFunctionType(toscaFunctionType1)
-            .orElseThrow(() -> new InvalidArgumentException("Could not convert a ToscaFunctionType to a ToscaGetFunctionType"))
+        final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition();
+        toscaGetFunction.setFunctionType(
+            toscaFunctionType.toString().equalsIgnoreCase(ToscaFunctionType.GET_PROPERTY.getName()) ? ToscaGetFunctionType.GET_PROPERTY : ToscaGetFunctionType.GET_ATTRIBUTE
         );
-        final List<String> getFunctionValue;
+        final Object functionValueObj = null != filterValueAsMap.get(toscaFunctionType1) ?
+            filterValueAsMap.get(toscaFunctionType1) : filterValueAsMap.get(toscaFunctionType);
+        if (!(functionValueObj instanceof List)) {
+            return Optional.empty();
+        }
+        final List<String> functionParameters;
         try {
-            getFunctionValue = (List<String>) filterValueAsMap.get(toscaFunctionType);
-        } catch (final Exception ignored) {
-            return Optional.of(toscaGetFunction);
+            functionParameters = ((List<Object>) functionValueObj).stream()
+                .map(object -> Objects.toString(object, null))
+                .collect(Collectors.toList());
+        } catch (final ClassCastException ignored) {
+            return Optional.empty();
         }
-        if (!getFunctionValue.isEmpty()) {
-            final Optional<PropertySource> propertySource = PropertySource.findType(getFunctionValue.get(0));
-            if (propertySource.isPresent()) {
-                toscaGetFunction.setPropertySource(propertySource.get());
-            } else {
-                toscaGetFunction.setPropertySource(PropertySource.INSTANCE);
-                toscaGetFunction.setSourceName(getFunctionValue.get(0));
+        if (functionParameters.size() < 2) {
+            return Optional.empty();
+        }
+        final String propertySourceType = functionParameters.get(0);
+        final PropertySource propertySource = PropertySource.findType(propertySourceType).orElse(null);
+        if (propertySource == PropertySource.SELF) {
+            toscaGetFunction.setPropertySource(propertySource);
+        } else {
+            toscaGetFunction.setPropertySource(PropertySource.INSTANCE);
+            toscaGetFunction.setSourceName(propertySourceType);
+        }
+        List<String> propertySourceIndex = functionParameters.subList(1, functionParameters.size());
+        List<String> propertySourcePath = new ArrayList<>();
+        propertySourcePath.add((String)propertySourceIndex.get(0));
+        if (propertySourceIndex.size() > 1 ) {
+            List<Object> indexParsedList = new ArrayList<Object>();
+            List<String> indexObjectList = propertySourceIndex.subList(1,propertySourceIndex.size());
+            boolean loopFlag = true;
+            for (String indexValue : indexObjectList) {
+                if (!indexValue.equalsIgnoreCase("INDEX") && !StringUtils.isNumeric(indexValue) && loopFlag) {
+                    propertySourcePath.add(indexValue);
+                } else {
+                    loopFlag = false;
+                    if (StringUtils.isNumeric(indexValue)) {
+                        indexParsedList.add(Integer.parseInt(indexValue));
+                    } else {
+                        indexParsedList.add(indexValue);
+                    }
+                }
             }
-            final List<String> propertyPathFromSource = getFunctionValue.subList(1, getFunctionValue.size());
-            toscaGetFunction.setPropertyPathFromSource(propertyPathFromSource);
-            toscaGetFunction.setPropertyName(propertyPathFromSource.get(propertyPathFromSource.size() - 1));
+            toscaGetFunction.setToscaIndexList(indexParsedList);
         }
+        toscaGetFunction.setPropertyPathFromSource(propertySourcePath);
+        final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1);
+        toscaGetFunction.setPropertyName(propertyName);
         return Optional.of(toscaGetFunction);
     }
 
     private static Optional<ToscaFunction> readLegacyGetInputConstraintValue(Map<?, ?> filterValueAsMap, Object toscaFunctionType) {
-        final var toscaGetFunction = new ToscaGetFunctionDataDefinition();
+        final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition();
         toscaGetFunction.setFunctionType(ToscaGetFunctionType.GET_INPUT);
-        final List<String> getFunctionValue;
-        final Object valueAsObject = filterValueAsMap.get(toscaFunctionType);
-        if (valueAsObject instanceof String) {
-            getFunctionValue = List.of((String) valueAsObject);
-        } else if (valueAsObject instanceof List) {
+        toscaGetFunction.setPropertySource(PropertySource.SELF);
+        final Object functionValueObj = filterValueAsMap.get(toscaFunctionType);
+        if (!(functionValueObj instanceof List) && !(functionValueObj instanceof String)) {
+            return Optional.empty();
+        }
+        if (functionValueObj instanceof String) {
+            toscaGetFunction.setPropertyPathFromSource(List.of((String) functionValueObj));
+        } else {
+            final List<String> functionParameters;
             try {
-                getFunctionValue = (List<String>) filterValueAsMap.get(toscaFunctionType);
-            } catch (final Exception ignored) {
+                functionParameters = ((List<Object>) functionValueObj).stream()
+                    .map(object -> Objects.toString(object, null))
+                    .collect(Collectors.toList());
+            } catch (final ClassCastException ignored) {
                 return Optional.empty();
             }
-        } else {
-            return Optional.empty();
-        }
-
-        toscaGetFunction.setPropertyPathFromSource(getFunctionValue);
-        if (!getFunctionValue.isEmpty()) {
-            toscaGetFunction.setPropertyName(getFunctionValue.get(getFunctionValue.size() - 1));
+            List<String> propertySourcePath = new ArrayList<>();
+            propertySourcePath.add((String)functionParameters.get(0));
+            if (functionParameters.size() > 1 ) {
+                List<Object> indexParsedList = new ArrayList<Object>();
+                List<String> indexObjectList = functionParameters.subList(1,functionParameters.size());
+                boolean loopFlag = true;
+                for (String indexValue : indexObjectList) {
+                    if (!indexValue.equalsIgnoreCase("INDEX") && !StringUtils.isNumeric(indexValue) && loopFlag) {
+                        propertySourcePath.add(indexValue);
+                    } else {
+                        loopFlag = false;
+                        if (StringUtils.isNumeric(indexValue)) {
+                            indexParsedList.add(Integer.parseInt(indexValue));
+                        } else {
+                            indexParsedList.add(indexValue);
+                        }
+                    }
+                }
+                toscaGetFunction.setToscaIndexList(indexParsedList);
+            }
+            toscaGetFunction.setPropertyPathFromSource(propertySourcePath);
         }
-        toscaGetFunction.setPropertySource(PropertySource.SELF);
+        final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1);
+        toscaGetFunction.setPropertyName(propertyName);
         return Optional.of(toscaGetFunction);
     }
 
index 86548fa..5684db2 100644 (file)
@@ -76,6 +76,17 @@ class PropertyFilterConstraintDataDefinitionHelperTest {
             List.of("property", "subProperty"), "subProperty", "Instance Name");
     }
 
+    @Test
+    void convertLegacyConstraintGetInputFromSelfTest() throws IOException {
+        final PropertyFilterConstraintDataDefinition propertyFilterConstraint =
+            PropertyFilterConstraintDataDefinitionHelper.convertLegacyConstraint(readConstraintFile("legacy-get_input-from-self.yaml"));
+        assertPropertyFilterConstraint(propertyFilterConstraint, "flavour_id", null, ConstraintType.EQUAL, FilterValueType.GET_INPUT);
+        assertTrue(propertyFilterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition);
+        final var toscaGetFunction = (ToscaGetFunctionDataDefinition) propertyFilterConstraint.getValue();
+        assertToscaGetFunction(toscaGetFunction, ToscaFunctionType.GET_INPUT, ToscaGetFunctionType.GET_INPUT, PropertySource.SELF,
+            List.of("SELF", "input", "subInput"), "subInput", null);
+    }
+
     @Test
     void convertLegacyConstraintGetAttributeFromInstanceTest() throws IOException {
         final PropertyFilterConstraintDataDefinition propertyFilterConstraint =
diff --git a/common-be/src/test/resources/nodeFilter/constraints/legacy-get_input-from-self.yaml b/common-be/src/test/resources/nodeFilter/constraints/legacy-get_input-from-self.yaml
new file mode 100644 (file)
index 0000000..a12444e
--- /dev/null
@@ -0,0 +1,6 @@
+flavour_id:
+  equal:
+    get_input:
+      - SELF
+      - input
+      - subInput
\ No newline at end of file