From df1d6ebebe45708040048abc33aebb8980a0c9f2 Mon Sep 17 00:00:00 2001 From: franciscovila Date: Tue, 20 Jun 2023 10:38:45 +0100 Subject: Support custom tosca functions in operation input values Issue-ID: SDC-4545 Signed-off-by: franciscovila Change-Id: Icd466d4e2e1d2136f6e41b5c345e9244d5f295f6 --- .../sdc/be/datatypes/enums/FilterValueType.java | 1 + ...opertyFilterConstraintDataDefinitionHelper.java | 269 ++++++++++++++++++++- 2 files changed, 267 insertions(+), 3 deletions(-) (limited to 'common-be/src/main') diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/FilterValueType.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/FilterValueType.java index 62a19b8041..30d86fda4e 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/FilterValueType.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/FilterValueType.java @@ -35,6 +35,7 @@ public enum FilterValueType { GET_INPUT("get_input", "service_input"), GET_ATTRIBUTE("get_attribute", null), YAML("yaml", null), + CUSTOM("custom", null), CONCAT("concat", null), SEVERAL("several", null); diff --git a/common-be/src/main/java/org/openecomp/sdc/be/utils/PropertyFilterConstraintDataDefinitionHelper.java b/common-be/src/main/java/org/openecomp/sdc/be/utils/PropertyFilterConstraintDataDefinitionHelper.java index 6377152a13..1f7459c59d 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/utils/PropertyFilterConstraintDataDefinitionHelper.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/utils/PropertyFilterConstraintDataDefinitionHelper.java @@ -22,17 +22,24 @@ package org.openecomp.sdc.be.utils; import java.util.ArrayList; +import java.util.HashMap; 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 java.util.stream.Stream; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.openecomp.sdc.be.config.Configuration; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.be.datatypes.elements.CustomYamlFunction; import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ToscaConcatFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaCustomFunction; import org.openecomp.sdc.be.datatypes.elements.ToscaFunction; import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionParameter; import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType; @@ -81,9 +88,16 @@ public class PropertyFilterConstraintDataDefinitionHelper { if (!(toscaFunctionTypeObject instanceof String)) { return Optional.empty(); } - final ToscaFunctionType toscaFunctionType = ToscaFunctionType.findType((String) toscaFunctionTypeObject).orElse(null); + ToscaFunctionType toscaFunctionType = ToscaFunctionType.findType((String) toscaFunctionTypeObject).orElse(null); if (toscaFunctionType == null) { - return Optional.empty(); + if (((String) toscaFunctionTypeObject).equalsIgnoreCase("$get_input_ext") || + ((String) toscaFunctionTypeObject).equalsIgnoreCase("$juel") || + ((String) toscaFunctionTypeObject).equalsIgnoreCase("$other")) { + toscaFunctionType = ToscaFunctionType.CUSTOM; + } + else { + return Optional.empty(); + } } switch (toscaFunctionType) { case GET_INPUT: @@ -93,11 +107,256 @@ public class PropertyFilterConstraintDataDefinitionHelper { return readLegacyGetPropertyConstraintValue(filterValueAsMap, toscaFunctionTypeObject, toscaFunctionType); case CONCAT: return readLegacyConcatConstraintValue(filterValueAsMap, toscaFunctionTypeObject); + case CUSTOM: + return handleCustomFunction((Map)filterValueAsMap, (String)toscaFunctionTypeObject); + default: + return Optional.empty(); + } + } + + private static Optional handleCustomFunction(Map toscaFunctionPropertyValueMap, String functionType) { + final ToscaCustomFunction toscaCustomFunction = new ToscaCustomFunction(); + toscaCustomFunction.setName(functionType.substring(1)); + final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType); + toscaCustomFunction.setToscaFunctionType(getCustomFunctionType(toscaCustomFunction.getName())); + if (ToscaFunctionType.GET_INPUT.equals(toscaCustomFunction.getToscaFunctionType())) { + return handleCustomFunctionGetInputType(toscaCustomFunction, functionValueObj); + } + return handelCustomFunctionCustomType(toscaCustomFunction, functionValueObj); + } + + private static Optional handleCustomFunctionGetInputType(ToscaCustomFunction toscaCustomFunction, Object functionValueObj) { + if (!(functionValueObj instanceof String) && !(functionValueObj instanceof List)) { + return Optional.empty(); + } + Map parameterMap = new HashMap<>(); + parameterMap.put(ToscaFunctionType.GET_INPUT.getName(), functionValueObj); + buildToscaFunctionBasedOnPropertyValue(parameterMap).ifPresent(toscaFunction -> { + if (toscaFunction instanceof ToscaFunctionParameter) { + toscaCustomFunction.addParameter((ToscaFunctionParameter) toscaFunction); + } + }); + return Optional.of(toscaCustomFunction); + } + + private static Optional buildToscaFunctionBasedOnPropertyValue(final Map toscaFunctionPropertyValueMap) { + if (!isPropertyValueToscaFunction(toscaFunctionPropertyValueMap)) { + return Optional.empty(); + } + final String functionType = toscaFunctionPropertyValueMap.keySet().iterator().next(); + final ToscaFunctionType toscaFunctionType = + ToscaFunctionType.findType(functionType).orElse(functionType.startsWith("$") ? ToscaFunctionType.CUSTOM : null); + if (toscaFunctionType == null) { + return Optional.empty(); + } + switch (toscaFunctionType) { + case GET_INPUT: { + return handleGetInputFunction(toscaFunctionPropertyValueMap, functionType); + } + case GET_PROPERTY: + case GET_ATTRIBUTE: { + return handleGetPropertyFunction(toscaFunctionPropertyValueMap, functionType, toscaFunctionType); + } + case CONCAT: + return handleConcatFunction(toscaFunctionPropertyValueMap, functionType); + case CUSTOM: + return handleCustomFunction(toscaFunctionPropertyValueMap, functionType); default: return Optional.empty(); } } + private static Optional handleConcatFunction(Map toscaFunctionPropertyValueMap, String functionType) { + final ToscaConcatFunction toscaConcatFunction = new ToscaConcatFunction(); + final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType); + if (!(functionValueObj instanceof List)) { + return Optional.empty(); + } + final List functionParameters = (List) functionValueObj; + if (functionParameters.size() < 2) { + return Optional.empty(); + } + functionParameters.forEach(parameter -> { + if (parameter instanceof String) { + final var stringParameter = new ToscaStringParameter(); + stringParameter.setValue((String) parameter); + toscaConcatFunction.addParameter(stringParameter); + return; + } + if (isPropertyValueToscaFunction(parameter)) { + buildToscaFunctionBasedOnPropertyValue((Map) parameter).ifPresent(toscaFunction -> { + if (toscaFunction instanceof ToscaFunctionParameter) { + toscaConcatFunction.addParameter((ToscaFunctionParameter) toscaFunction); + } + }); + return; + } + final var customYamlFunction = new CustomYamlFunction(); + customYamlFunction.setYamlValue(parameter); + toscaConcatFunction.addParameter(customYamlFunction); + }); + return Optional.of(toscaConcatFunction); + } + + private static Optional handleGetPropertyFunction(Map toscaFunctionPropertyValueMap, String functionType, + ToscaFunctionType toscaFunctionType) { + final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition(); + toscaGetFunction.setFunctionType( + toscaFunctionType == ToscaFunctionType.GET_PROPERTY ? ToscaGetFunctionType.GET_PROPERTY : ToscaGetFunctionType.GET_ATTRIBUTE + ); + final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType); + if (!(functionValueObj instanceof List)) { + return Optional.empty(); + } + final List functionParameters; + try { + functionParameters = ((List) functionValueObj).stream() + .map(object -> Objects.toString(object, null)) + .collect(Collectors.toList()); + } catch (final ClassCastException ignored) { + return Optional.empty(); + } + 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 propertySourceIndex = functionParameters.subList(1, functionParameters.size()); + List propertySourcePath = new ArrayList<>(); + propertySourcePath.add((String)propertySourceIndex.get(0)); + if (propertySourceIndex.size() > 1 ) { + List indexParsedList = new ArrayList(); + List 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); + } + } + } + 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 handleGetInputFunction(Map toscaFunctionPropertyValueMap, String functionType) { + final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition(); + toscaGetFunction.setFunctionType(ToscaGetFunctionType.GET_INPUT); + toscaGetFunction.setPropertySource(PropertySource.SELF); + final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType); + if (!(functionValueObj instanceof List) && !(functionValueObj instanceof String)) { + return Optional.empty(); + } + if (functionValueObj instanceof String) { + toscaGetFunction.setPropertyPathFromSource(List.of((String) functionValueObj)); + } else { + final List functionParameters; + try { + functionParameters = ((List) functionValueObj).stream() + .map(object -> Objects.toString(object, null)) + .collect(Collectors.toList()); + } catch (final ClassCastException ignored) { + return Optional.empty(); + } + List propertySourcePath = new ArrayList<>(); + propertySourcePath.add((String)functionParameters.get(0)); + if (functionParameters.size() > 1 ) { + List indexParsedList = new ArrayList(); + List 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); + } + final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1); + toscaGetFunction.setPropertyName(propertyName); + return Optional.of(toscaGetFunction); + } + + public static boolean isPropertyValueToscaFunction(final Object propValueObj) { + if (propValueObj instanceof Map) { + final Map propValueMap = (Map) propValueObj; + if (propValueMap.keySet().size() > 1) { + return false; + } + if (propValueMap.keySet().stream().anyMatch(keyValue -> keyValue.startsWith("$"))) { + return true; + } + + return Stream.of(ToscaFunctionType.GET_INPUT, ToscaFunctionType.GET_PROPERTY, ToscaFunctionType.GET_ATTRIBUTE, ToscaFunctionType.CONCAT) + .anyMatch(type -> propValueMap.containsKey(type.getName())); + } + return false; + } + + private static ToscaFunctionType getCustomFunctionType(String name) { + List customFunctions = + ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultCustomToscaFunctions(); + if (CollectionUtils.isEmpty(customFunctions)) { + return ToscaFunctionType.CUSTOM; + } + Optional optionalFunc = customFunctions.stream().filter(func -> func.getName().equals(name)).findFirst(); + if (optionalFunc.isEmpty()) { + return ToscaFunctionType.CUSTOM; + } + String type = optionalFunc.get().getType(); + return ToscaFunctionType.findType(type).get(); + } + + private static Optional handelCustomFunctionCustomType(ToscaCustomFunction toscaCustomFunction, Object functionValueObj) { + if (!(functionValueObj instanceof List)) { + return Optional.empty(); + } + final List functionParameters = (List) functionValueObj; + functionParameters.forEach(parameter -> { + if (parameter instanceof String) { + final var stringParameter = new ToscaStringParameter(); + stringParameter.setValue((String) parameter); + toscaCustomFunction.addParameter(stringParameter); + return; + } + if (isPropertyValueToscaFunction(parameter)) { + buildToscaFunctionBasedOnPropertyValue((Map) parameter).ifPresent(toscaFunction -> { + if (toscaFunction instanceof ToscaFunctionParameter) { + toscaCustomFunction.addParameter((ToscaFunctionParameter) toscaFunction); + } + }); + return; + } + final var customYamlFunction = new CustomYamlFunction(); + customYamlFunction.setYamlValue(parameter); + toscaCustomFunction.addParameter(customYamlFunction); + }); + return Optional.of(toscaCustomFunction); + } + public static Optional convertFromToscaFunctionType(final ToscaFunctionType toscaFunctionType) { return FilterValueType.findByName(toscaFunctionType.getName()); } @@ -244,8 +503,12 @@ public class PropertyFilterConstraintDataDefinitionHelper { if (valueAsMap.containsKey(ToscaFunctionType.GET_INPUT.getName())) { return FilterValueType.GET_INPUT; } + if (valueAsMap.containsKey("$get_input_ext") || + valueAsMap.containsKey("$juel") || + valueAsMap.containsKey("$other")) { + return FilterValueType.CUSTOM; + } } - return FilterValueType.STATIC; } -- cgit 1.2.3-korg