From 35ee855d664246d55694f06b61bde82277cb2c5c Mon Sep 17 00:00:00 2001 From: JvD_Ericsson Date: Wed, 29 Mar 2023 12:34:59 +0100 Subject: Backend support for custom functions Issue-ID: SDC-4455 Signed-off-by: JvD_Ericsson Change-Id: Idb0fd38681066ba9d541f8564c85e316cf03e927 --- .../be/datatypes/elements/ToscaCustomFunction.java | 62 ++++++++++++++++++++++ .../elements/ToscaFunctionJsonDeserializer.java | 37 ++++++++++--- .../be/datatypes/elements/ToscaFunctionType.java | 1 + .../ToscaFunctionJsonDeserializerTest.java | 50 +++++++++++++++++ .../customFunction.json | 45 ++++++++++++++++ 5 files changed, 188 insertions(+), 7 deletions(-) create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaCustomFunction.java create mode 100644 common-be/src/test/resources/toscaFunctionJsonDeserializer/customFunction.json (limited to 'common-be') diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaCustomFunction.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaCustomFunction.java new file mode 100644 index 0000000000..3f0c4fa8a5 --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaCustomFunction.java @@ -0,0 +1,62 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.datatypes.elements; + +import com.google.gson.Gson; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Getter +@Setter +public class ToscaCustomFunction implements ToscaFunction, ToscaFunctionParameter { + + private String name; + private List parameters = new ArrayList<>(); + + @Override + public ToscaFunctionType getType() { + return ToscaFunctionType.CUSTOM; + } + + @Override + public String getValue() { + return new Gson().toJson(getJsonObjectValue()); + } + + @Override + public Object getJsonObjectValue() { + return Map.of( + "$" + name, + parameters.stream().map(ToscaFunctionParameter::getJsonObjectValue).collect(Collectors.toList()) + ); + } + + public void addParameter(final ToscaFunctionParameter functionParameter) { + this.parameters.add(functionParameter); + } + +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializer.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializer.java index c262699cc2..ec3459989e 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializer.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaFunctionJsonDeserializer.java @@ -81,6 +81,10 @@ public class ToscaFunctionJsonDeserializer extends StdDeserializer functionParameterList = getParameters(concatFunctionJsonNode, context); + toscaConcatFunction.setParameters(functionParameterList); + return toscaConcatFunction; + } + + private ToscaCustomFunction deserializeCustomFunction(final JsonNode customFunctionJsonNode, + final DeserializationContext context) throws IOException { + final var toscaCustomFunction = new ToscaCustomFunction(); + final String name = getAsTextOrElseNull(customFunctionJsonNode, "name"); + if (name == null) { + throw context.instantiationException(List.class, "Expecting a string for the 'name' entry"); + } + toscaCustomFunction.setName(name); + List functionParameterList = getParameters(customFunctionJsonNode, context); + toscaCustomFunction.setParameters(functionParameterList); + return toscaCustomFunction; + } + + private List getParameters(final JsonNode functionJsonNode, final DeserializationContext context) throws IOException { final List functionParameterList = new ArrayList<>(); - final JsonNode parametersNode = concatFunctionJsonNode.get("parameters"); + final JsonNode parametersNode = functionJsonNode.get("parameters"); if (parametersNode == null) { - return toscaConcatFunction; + return functionParameterList; } if (!parametersNode.isArray()) { throw context.instantiationException(List.class, "Expecting an array for the 'parameters' entry"); } + for (final JsonNode parameterNode : parametersNode) { final JsonNode typeJsonNode = parameterNode.get("type"); if (typeJsonNode == null) { - throw context.instantiationException(ToscaConcatFunction.class, "TOSCA concat function parameter type attribute not provided"); + throw context.instantiationException(ToscaFunction.class, "TOSCA function parameter type attribute not provided"); } final String parameterType = typeJsonNode.asText(); final ToscaFunctionType toscaFunctionType = ToscaFunctionType.findType(parameterType) - .orElseThrow(() -> context.instantiationException(ToscaConcatFunction.class, - String.format("Invalid TOSCA concat function parameter type '%s'", parameterType)) + .orElseThrow(() -> context.instantiationException(ToscaFunction.class, + String.format("Invalid TOSCA function parameter type '%s'", parameterType)) ); if (toscaFunctionType == ToscaFunctionType.STRING) { final ToscaStringParameter toscaStringParameter = new ToscaStringParameter(); @@ -171,8 +195,7 @@ public class ToscaFunctionJsonDeserializer extends StdDeserializer new Yaml().load(toscaFunction.getValue())); } + @Test + void testCustomToscaFunction() throws IOException { + //given + final String toscaCustomFunction = Files.readString(TEST_RESOURCES_PATH.resolve("customFunction.json")); + //when + final ToscaFunction toscaFunction = parseToscaFunction(toscaCustomFunction); + //then + assertTrue(toscaFunction instanceof ToscaCustomFunction); + final Object yamlObject = new Yaml().load(toscaFunction.getValue()); + assertTrue(yamlObject instanceof Map); + final Map yamlMap = (Map) yamlObject; + final Object customFunctionObj = yamlMap.get("$" + ((ToscaCustomFunction) toscaFunction).getName()); + assertNotNull(customFunctionObj); + assertTrue(customFunctionObj instanceof List); + final List customFunctionParameters = (List) customFunctionObj; + assertEquals(3, customFunctionParameters.size(), "Expecting three parameters"); + assertEquals("string1", customFunctionParameters.get(0)); + + assertTrue(customFunctionParameters.get(1) instanceof Map); + final Map parameter1Map = (Map) customFunctionParameters.get(1); + assertNotNull(parameter1Map.get(ToscaFunctionType.GET_ATTRIBUTE.getName())); + assertTrue(parameter1Map.get(ToscaFunctionType.GET_ATTRIBUTE.getName()) instanceof List); + List getAttributeParameters = (List) parameter1Map.get(ToscaFunctionType.GET_ATTRIBUTE.getName()); + assertEquals(2, getAttributeParameters.size(), "Expecting two parameters in the get_attribute function"); + assertEquals("SELF", getAttributeParameters.get(0)); + assertEquals("descriptor_id", getAttributeParameters.get(1)); + + assertTrue(customFunctionParameters.get(2) instanceof Map); + final Map parameter2Map = (Map) customFunctionParameters.get(2); + Object customFunctionObj2 = parameter2Map.get(parameter2Map.keySet().stream().iterator().next()); + assertNotNull(customFunctionObj2); + assertTrue(customFunctionObj2 instanceof List); + List customParameters = (List) customFunctionObj2; + assertEquals(2, customParameters.size(), "Expecting two parameters in the sub custom function"); + assertTrue(customParameters.get(0) instanceof Map); + final Map concatFunctionValueMap = (Map) customParameters.get(0); + assertNotNull(concatFunctionValueMap.get(ToscaFunctionType.CONCAT.getName())); + assertTrue(concatFunctionValueMap.get(ToscaFunctionType.CONCAT.getName()) instanceof List); + List concatParameters = (List) concatFunctionValueMap.get(ToscaFunctionType.CONCAT.getName()); + assertEquals(2, concatParameters.size(), "Expecting two parameters in the sub concat function"); + assertEquals("string2", concatParameters.get(0)); + assertTrue(concatParameters.get(1) instanceof Map); + Map yamlFunctionValueMap = (Map) concatParameters.get(1); + assertTrue(yamlFunctionValueMap.get("myList") instanceof List); + assertTrue(yamlFunctionValueMap.get("get_something") instanceof List); + assertTrue(yamlFunctionValueMap.get("string") instanceof String); + + assertEquals("string3", customParameters.get(1)); + } + private ToscaFunction parseToscaFunction(final String toscaFunctionJson) throws JsonProcessingException { return new ObjectMapper().readValue(toscaFunctionJson, ToscaFunction.class); } diff --git a/common-be/src/test/resources/toscaFunctionJsonDeserializer/customFunction.json b/common-be/src/test/resources/toscaFunctionJsonDeserializer/customFunction.json new file mode 100644 index 0000000000..0042975e29 --- /dev/null +++ b/common-be/src/test/resources/toscaFunctionJsonDeserializer/customFunction.json @@ -0,0 +1,45 @@ +{ + "type": "CUSTOM", + "name": "first_custom_function_name", + "parameters": [ + { + "type": "STRING", + "value": "string1" + }, + { + "type": "GET_ATTRIBUTE", + "propertyUniqueId": "36897651-f5e5-4603-8064-b60c771a3c37.descriptor_id", + "propertyName": "descriptor_id", + "propertySource": "SELF", + "sourceUniqueId": "36897651-f5e5-4603-8064-b60c771a3c37", + "sourceName": "testService", + "functionType": "GET_ATTRIBUTE", + "propertyPathFromSource": [ + "descriptor_id" + ] + }, + { + "type": "CUSTOM", + "name": "second_custom_function_name", + "parameters": [ + { + "type": "CONCAT", + "parameters": [ + { + "type": "STRING", + "value": "string2" + }, + { + "type": "YAML", + "value": "myList: [1, two, three three]\nget_something: [SELF, something]\nstring: this is my string\n" + } + ] + }, + { + "type": "STRING", + "value": "string3" + } + ] + } + ] +} \ No newline at end of file -- cgit