001package com.randomnoun.common.jexl.eval;
002
003/* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a
004 * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
005 */
006import java.util.HashMap;
007import java.util.Map;
008
009/**
010 * Provides variables and functions for an expression to be evaluated with
011 *
012 * 
013 * @author knoxg
014 */
015public class EvalContext
016{
017    /** Contains a map of variable names to variable values */
018    private Map<String, Object> variables = new HashMap<String, Object>();
019
020    /** Contains a map of function names to EvalFunction values */
021    private Map<String, EvalFunction> functions = new HashMap<String, EvalFunction>();
022
023    /** Sets all variables accessable to an expression. */
024    public void setVariables(Map<String, Object> variables)
025    {
026        this.variables = variables;
027    }
028
029    /** Set a specific variable binding */
030    public void setVariable(String name, Object value)
031    {
032        variables.put(name, value);
033    }
034
035    /** Removes a specific variable binding */
036    public void unsetVariable(String name)
037    {
038        variables.remove(name);
039    }
040
041    /** Returns the value of a variable (used in the Evaluator class). */
042    public Object getVariable(String varName)
043    {
044        return variables.get(varName);
045    }
046
047    /** Returns true if the variable exists. */
048    public boolean hasVariable(String varName)
049    {
050        return variables.containsKey(varName);
051    }
052
053    /** Sets all variables accessible to an expression. */
054    public void setFunctions(Map<String, EvalFunction> functions)
055    {
056        this.functions = functions;
057    }
058
059    /** Set a specific function */
060    public void setFunction(String name, EvalFunction function)
061    {
062        functions.put(name, function);
063    }
064
065    /** Returns the value of a variable (used in the Evaluator class). */
066    public Object getFunction(String function)
067    {
068        return functions.get(function);
069    }
070
071    /** Returns a component of a compound variable (which must currently be a Map object).
072     * The component name is the key of the map. 
073     * e.g. if a Map variable called 'x' contains a key 'y' with the value
074     * 'z', then the following code could be used to retrieve this value:
075     *
076     * <pre>
077     *   x = evalContext.getVariable("x")
078     *   value = evalContext.getVariableComponent(x, "x", "y")  // evaluates to 'z'
079     * </pre>
080     *
081     * <p>Note that this is only useful in the Evaluator to retrieve compound variables,
082     * outside the evaluator you should be just be evaluating the value "x.y" directly.
083     *
084     * @param varObj the compound variable value that is being evaluated (as returned
085     *   by the getVariable() method)
086     * @param baseName the name of the variable
087     * @param componentName the name of the component in varObj to return.
088     *
089     * */
090    public Object getVariableComponent(Object varObj, String baseName,
091        String componentName)
092        throws EvalException
093    {
094        if (varObj == null) {
095            throw new EvalException("Can not retrieve component '" + componentName +
096                "' from '" + baseName + "'; base is null");
097        }
098
099        if (varObj instanceof Map) {
100            return ((Map<?, ?>) varObj).get(componentName);
101        } else {
102            throw new EvalException("Can not retrieve component '" + componentName +
103                "' from '" + baseName + "'; base is of type '" +
104                varObj.getClass().getName() + "'");
105        }
106    }
107
108    /**
109     * DOCUMENT ME!
110     *
111     * @param varObj DOCUMENT ME!
112     * @param baseName DOCUMENT ME!
113     * @param componentName DOCUMENT ME!
114     *
115     * @return DOCUMENT ME!
116     */
117    public boolean hasVariableComponent(Object varObj, String baseName,
118        String componentName)
119    {
120        if (varObj == null) {
121            throw new EvalException("Can not retrieve component '" + componentName +
122                "' from '" + baseName + "'; base is null");
123        }
124
125        if (varObj instanceof Map) {
126            return ((Map<?, ?>) varObj).containsKey(componentName);
127        } else {
128            throw new EvalException("Can not retrieve component '" + componentName +
129                "' from '" + baseName + "'; base is of type '" +
130                varObj.getClass().getName() + "'");
131        }
132    }
133
134}