class FunctionEvaluator {

    public static AbstractPropertyValue tryResolveValue(FunctionEvaluatorContext evaluatorContext, AbstractInstantiableTemplate template,
            Map<String, AbstractPropertyValue> properties, AbstractPropertyValue evaluatedProperty) {
        if (evaluatedProperty == null) {
            // There is nothing to be evaluated.
            return null;
        }
        if (evaluatedProperty instanceof PropertyValue) {
            // This is a value already so just return it.
            return evaluatedProperty;
        }
        if (containGetSecretFunction(evaluatedProperty)) {
            return evaluatedProperty;
        }
        if (evaluatedProperty instanceof FunctionPropertyValue) {
            FunctionPropertyValue evaluatedFunction = (FunctionPropertyValue) evaluatedProperty;
            switch (evaluatedFunction.getFunction()) {
            case ToscaFunctionConstants.GET_INPUT:
                String inputName = evaluatedFunction.getParameters().get(0);
                return evaluatorContext.getInputs().get(inputName);
            case ToscaFunctionConstants.GET_PROPERTY:
                // Perform the get property evaluation.
                return getProperty(evaluatorContext, template, properties, evaluatedFunction);
            default:
                throw new IllegalArgumentException("GET_ATTRIBUTE or GET_OPERATION_OUTPUT cannot be defined on a property.");
            }
        }
        if (evaluatedProperty instanceof ConcatPropertyValue) {
            // Perform the concat evaluation
            return concat(evaluatorContext, template, properties, (ConcatPropertyValue) evaluatedProperty);
        }
        throw new IllegalArgumentException("AbstractPropertyValue must be one of null, a secret, PropertyValue, FunctionPropertyValue or ConcatPropertyValue");
    }

}