Fix 'JUEL expression syntax prevents download'-bug
[sdc.git] / common-be / src / main / java / org / openecomp / sdc / be / datatypes / elements / ToscaFunctionJsonDeserializer.java
index c262699..dbef13e 100644 (file)
@@ -26,14 +26,19 @@ import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.google.common.base.CharMatcher;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 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.enums.PropertySource;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.util.CollectionUtils;
 import org.yaml.snakeyaml.Yaml;
 
 public class ToscaFunctionJsonDeserializer extends StdDeserializer<ToscaFunction> {
@@ -81,6 +86,10 @@ public class ToscaFunctionJsonDeserializer extends StdDeserializer<ToscaFunction
             return this.deserializeYamlFunction(node, context);
         }
 
+        if (toscaFunctionType == ToscaFunctionType.CUSTOM) {
+            return this.deserializeCustomFunction(node, context);
+        }
+
         return null;
     }
 
@@ -109,6 +118,8 @@ public class ToscaFunctionJsonDeserializer extends StdDeserializer<ToscaFunction
         toscaGetFunction.setSourceUniqueId(getAsTextOrElseNull(node, "sourceUniqueId"));
         toscaGetFunction.setPropertyName(getAsTextOrElseNull(node, "propertyName"));
         toscaGetFunction.setPropertyUniqueId(getAsTextOrElseNull(node, "propertyUniqueId"));
+        toscaGetFunction.setToscaIndexList(getNumberAsTextOrElseNull(node, "toscaIndexList", context));
+
         final String propertySource = getAsTextOrElseNull(node, "propertySource");
         if (StringUtils.isNotEmpty(propertySource)) {
             final PropertySource propertySource1 = PropertySource.findType(propertySource).orElseThrow(() ->
@@ -141,38 +152,107 @@ public class ToscaFunctionJsonDeserializer extends StdDeserializer<ToscaFunction
         return jsonNode.asText();
     }
 
+    private List<Object> getNumberAsTextOrElseNull(final JsonNode node, final String fieldName, final DeserializationContext context)
+        throws JsonMappingException {
+        List<Object> toscaIndexList = new ArrayList<Object>();
+        final JsonNode jsonNode = node.get(fieldName);
+        if (jsonNode != null) {
+            if (!jsonNode.isArray()) {
+                throw context.instantiationException(ToscaGetFunctionDataDefinition.class, "Expecting an array for toscaIndexList attribute");
+            }
+
+            jsonNode.forEach(nodeValue -> {
+                String indexValue = nodeValue.asText();
+                if (StringUtils.isNumeric(indexValue)) {
+                    toscaIndexList.add(Integer.parseInt(indexValue));
+                } else {
+                    toscaIndexList.add(indexValue);
+                }
+            });
+        }
+        return toscaIndexList;
+    }
+
     private ToscaConcatFunction deserializeConcatFunction(final JsonNode concatFunctionJsonNode,
                                                           final DeserializationContext context) throws IOException {
         final var toscaConcatFunction = new ToscaConcatFunction();
+        List<ToscaFunctionParameter> 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);
+        toscaCustomFunction.setToscaFunctionType(getCustomFunctionType(name));
+        List<ToscaFunctionParameter> functionParameterList = getParameters(customFunctionJsonNode, context);
+        toscaCustomFunction.setParameters(functionParameterList);
+        if (ToscaFunctionType.GET_INPUT.equals(toscaCustomFunction.getToscaFunctionType())) {
+            validateGetInput(toscaCustomFunction, context);
+        }
+        return toscaCustomFunction;
+    }
+
+    private ToscaFunctionType getCustomFunctionType(String name) {
+        List<Configuration.CustomToscaFunction> customFunctions =
+            ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultCustomToscaFunctions();
+        if (CollectionUtils.isEmpty(customFunctions)) {
+            return ToscaFunctionType.CUSTOM;
+        }
+        Optional<Configuration.CustomToscaFunction> 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 void validateGetInput(ToscaCustomFunction toscaCustomFunction, final DeserializationContext context) throws IOException {
+        List<ToscaFunctionParameter> functionParameterList = toscaCustomFunction.getParameters();
+        if (functionParameterList.size() != 1) {
+            throw context.instantiationException(List.class, "Custom GET_INPUT function must contain one GET_INPUT parameter");
+        }
+        ToscaFunctionParameter parameter = functionParameterList.get(0);
+        if (!ToscaFunctionType.GET_INPUT.equals(parameter.getType())) {
+            throw context.instantiationException(List.class, "Custom GET_INPUT function must contain a GET_INPUT parameter");
+        }
+    }
+
+    private List<ToscaFunctionParameter> getParameters(final JsonNode functionJsonNode, final DeserializationContext context) throws IOException {
         final List<ToscaFunctionParameter> 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();
-                toscaStringParameter.setValue(parameterNode.get("value").asText());
+                toscaStringParameter.setValue(CharMatcher.anyOf("\"\'[] ").trimFrom(parameterNode.get("value").asText()));
                 functionParameterList.add(toscaStringParameter);
             } else {
                 final ToscaFunction toscaFunction = this.deserializeToscaFunction(parameterNode, context);
                 functionParameterList.add((ToscaFunctionParameter) toscaFunction);
             }
         }
-        toscaConcatFunction.setParameters(functionParameterList);
-        return toscaConcatFunction;
+        return functionParameterList;
     }
 
 }