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> {
return this.deserializeYamlFunction(node, context);
}
+ if (toscaFunctionType == ToscaFunctionType.CUSTOM) {
+ return this.deserializeCustomFunction(node, context);
+ }
+
return null;
}
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(() ->
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;
}
}