org.apache.commons.ognl.Ognl.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.commons.ognl.Ognl.java

Source

package org.apache.commons.ognl;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import org.apache.commons.ognl.enhance.ExpressionAccessor;

import java.io.StringReader;
import java.util.Map;

/**
 * <p>
 * This class provides static methods for parsing and interpreting OGNL expressions.
 * </p>
 * <p>
 * The simplest use of the Ognl class is to get the value of an expression from an object, without extra context or
 * pre-parsing.
 * </p>
 * 
 * <pre>
 * 
 * import org.apache.commons.ognl.Ognl;
 * import org.apache.commons.ognl.OgnlException;
 * ...
 * try
 * {
 *     result = Ognl.getValue( expression, root );
 * }
 * catch ( OgnlException ex )
 * {
 *     // Report error or recover
 * }
 * 
 * </pre>
 * <p>
 * This will parse the expression given and evaluate it against the root object given, returning the result. If there is
 * an error in the expression, such as the property is not found, the exception is encapsulated into an
 * {@link org.apache.commons.ognl.OgnlException OgnlException}.
 * </p>
 * <p>
 * Other more sophisticated uses of Ognl can pre-parse expressions. This provides two advantages: in the case of
 * user-supplied expressions it allows you to catch parse errors before evaluation and it allows you to cache parsed
 * expressions into an AST for better speed during repeated use. The pre-parsed expression is always returned as an
 * <code>Object</code> to simplify use for programs that just wish to store the value for repeated use and do not care
 * that it is an AST. If it does care it can always safely cast the value to an <code>AST</code> type.
 * </p>
 * <p>
 * The Ognl class also takes a <I>context map</I> as one of the parameters to the set and get methods. This allows you
 * to put your own variables into the available namespace for OGNL expressions. The default context contains only the
 * <code>#root</code> and <code>#context</code> keys, which are required to be present. The
 * <code>addDefaultContext(Object, Map)</code> method will alter an existing <code>Map</code> to put the defaults in.
 * Here is an example that shows how to extract the <code>documentName</code> property out of the root object and append
 * a string with the current user name in parens:
 * </p>
 * 
 * <pre>
 * 
 * private Map&lt;String, Object&gt; context = new HashMap&lt;String, Object&gt;();
 * ...
 * public void setUserName( String value )
 * {
 *     context.put("userName", value);
 * }
 * ...
 * try
 * {
 *     // get value using our own custom context map
 *     result = Ognl.getValue( "documentName + \" (\" + ((#userName == null) ? \"&lt;nobody&gt;\" : #userName ) +
 * \")\"", context, root );
 * }
 * catch ( OgnlException ex )
 * {
 *     // Report error or recover
 * }
 * 
 * </pre>
 */
public abstract class Ognl {

    /**
     * Parses the given OGNL expression and returns a tree representation of the expression that can be used by
     * <code>Ognl</code> static methods.
     * 
     * @param expression the OGNL expression to be parsed
     * @return a tree representation of the expression
     * @throws ExpressionSyntaxException if the expression is malformed
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static Object parseExpression(String expression) throws OgnlException {
        try {
            OgnlParser parser = new OgnlParser(new StringReader(expression));
            return parser.topLevelExpression();
        } catch (ParseException e) {
            throw new ExpressionSyntaxException(expression, e);
        } catch (TokenMgrError e) {
            throw new ExpressionSyntaxException(expression, e);
        }
    }

    /**
     * Parses and compiles the given expression using the {@link org.apache.commons.ognl.enhance.OgnlExpressionCompiler}
     * returned from
     * {@link org.apache.commons.ognl.OgnlRuntime#getCompiler(OgnlContext)}.
     * 
     * @param context The context to use.
     * @param root The root object for the given expression.
     * @param expression The expression to compile.
     * @return The node with a compiled accessor set on {@link org.apache.commons.ognl.Node#getAccessor()} if
     * compilation was successfull.
     *         In instances where compilation wasn't possible because of a partially null expression the
     *         {@link ExpressionAccessor} instance may be null and the compilation of this expression still possible at
     *         some as yet indertermined point in the future.
     * @throws Exception If a compilation error occurs.
     */
    public static Node compileExpression(OgnlContext context, Object root, String expression) throws Exception {
        Node expr = (Node) Ognl.parseExpression(expression);

        OgnlRuntime.compileExpression(context, expr, root);

        return expr;
    }

    /**
     * Creates and returns a new standard naming context for evaluating an OGNL expression.
     * 
     * @param root the root of the object graph
     * @return a new Map with the keys <code>root</code> and <code>context</code> set appropriately
     */
    public static Map<String, Object> createDefaultContext(Object root) {
        return addDefaultContext(root, null, null, null, new OgnlContext());
    }

    /**
     * Creates and returns a new standard naming context for evaluating an OGNL expression.
     * 
     * @param root The root of the object graph.
     * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
     * @return a new OgnlContext with the keys <code>root</code> and <code>context</code> set appropriately
     */
    public static Map<String, Object> createDefaultContext(Object root, ClassResolver classResolver) {
        return addDefaultContext(root, classResolver, null, null, new OgnlContext());
    }

    /**
     * Creates and returns a new standard naming context for evaluating an OGNL expression.
     * 
     * @param root The root of the object graph.
     * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
     * @param converter Converter used to convert return types of an expression in to their desired types.
     * @return a new Map with the keys <code>root</code> and <code>context</code> set appropriately
     */
    public static Map<String, Object> createDefaultContext(Object root, ClassResolver classResolver,
            TypeConverter converter) {
        return addDefaultContext(root, classResolver, converter, null, new OgnlContext());
    }

    /**
     * Creates and returns a new standard naming context for evaluating an OGNL expression.
     * 
     * @param root The root of the object graph.
     * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
     * @param converter Converter used to convert return types of an expression in to their desired types.
     * @param memberAccess Java security handling object to determine semantics for accessing normally private/protected
     *            methods / fields.
     * @return a new Map with the keys <code>root</code> and <code>context</code> set appropriately
     */
    public static Map<String, Object> createDefaultContext(Object root, ClassResolver classResolver,
            TypeConverter converter, MemberAccess memberAccess) {
        return addDefaultContext(root, classResolver, converter, memberAccess, new OgnlContext());
    }

    /**
     * Appends the standard naming context for evaluating an OGNL expression into the context given so that cached maps
     * can be used as a context.
     * 
     * @param root the root of the object graph
     * @param context the context to which OGNL context will be added.
     * @return Context Map with the keys <code>root</code> and <code>context</code> set appropriately
     */
    public static Map<String, Object> addDefaultContext(Object root, Map<String, Object> context) {
        return addDefaultContext(root, null, null, null, context);
    }

    /**
     * Appends the standard naming context for evaluating an OGNL expression into the context given so that cached maps
     * can be used as a context.
     * 
     * @param root The root of the object graph.
     * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
     * @param context The context to which OGNL context will be added.
     * @return Context Map with the keys <code>root</code> and <code>context</code> set appropriately
     */
    public static Map<String, Object> addDefaultContext(Object root, ClassResolver classResolver,
            Map<String, Object> context) {
        return addDefaultContext(root, classResolver, null, null, context);
    }

    /**
     * Appends the standard naming context for evaluating an OGNL expression into the context given so that cached maps
     * can be used as a context.
     * 
     * @param root The root of the object graph.
     * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
     * @param converter Converter used to convert return types of an expression in to their desired types.
     * @param context The context to which OGNL context will be added.
     * @return Context Map with the keys <code>root</code> and <code>context</code> set appropriately
     */
    public static Map<String, Object> addDefaultContext(Object root, ClassResolver classResolver,
            TypeConverter converter, Map<String, Object> context) {
        return addDefaultContext(root, classResolver, converter, null, context);
    }

    /**
     * Appends the standard naming context for evaluating an OGNL expression into the context given so that cached maps
     * can be used as a context.
     * 
     * @param root the root of the object graph
     * @param classResolver The class loading resolver that should be used to resolve class references.
     * @param converter The type converter to be used by default.
     * @param memberAccess Definition for handling private/protected access.
     * @param context Default context to use, if not an {@link OgnlContext} will be dumped into a new
     *            {@link OgnlContext} object.
     * @return Context Map with the keys <code>root</code> and <code>context</code> set appropriately
     */
    public static Map<String, Object> addDefaultContext(Object root, ClassResolver classResolver,
            TypeConverter converter, MemberAccess memberAccess, Map<String, Object> context) {
        OgnlContext result;

        if (!(context instanceof OgnlContext)) {
            result = new OgnlContext();
            result.setValues(context);
        } else {
            result = (OgnlContext) context;
        }
        if (classResolver != null) {
            result.setClassResolver(classResolver);
        }
        if (converter != null) {
            result.setTypeConverter(converter);
        }
        if (memberAccess != null) {
            result.setMemberAccess(memberAccess);
        }

        result.setRoot(root);
        return result;
    }

    /**
     * Configures the {@link ClassResolver} to use for the given context. Will be used during expression parsing /
     * execution to resolve class names.
     * 
     * @param context The context to place the resolver.
     * @param classResolver The resolver to use to resolve classes.
     */
    public static void setClassResolver(Map<String, Object> context, ClassResolver classResolver) {
        context.put(OgnlContext.CLASS_RESOLVER_CONTEXT_KEY, classResolver);
    }

    /**
     * Gets the previously stored {@link ClassResolver} for the given context - if any.
     * 
     * @param context The context to get the configured resolver from.
     * @return The resolver instance, or null if none found.
     */
    public static ClassResolver getClassResolver(Map<String, Object> context) {
        return (ClassResolver) context.get(OgnlContext.CLASS_RESOLVER_CONTEXT_KEY);
    }

    /**
     * Configures the type converter to use for a given context. This will be used to convert into / out of various java
     * class types.
     * 
     * @param context The context to configure it for.
     * @param converter The converter to use.
     */
    public static void setTypeConverter(Map<String, Object> context, TypeConverter converter) {
        context.put(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY, converter);
    }

    /**
     * Gets the currently configured {@link TypeConverter} for the given context - if any.
     * 
     * @param context The context to get the converter from.
     * @return The converter - or null if none found.
     */
    public static TypeConverter getTypeConverter(Map<String, Object> context) {
        return (TypeConverter) context.get(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY);
    }

    /**
     * Configures the specified context with a {@link MemberAccess} instance for handling field/method protection
     * levels.
     * 
     * @param context The context to configure.
     * @param memberAccess The access resolver to configure the context with.
     */
    public static void setMemberAccess(Map<String, Object> context, MemberAccess memberAccess) {
        context.put(OgnlContext.MEMBER_ACCESS_CONTEXT_KEY, memberAccess);
    }

    /**
     * Gets the currently stored {@link MemberAccess} object for the given context - if any.
     * 
     * @param context The context to get the object from.
     * @return The configured {@link MemberAccess} instance in the specified context - or null if none found.
     */
    public static MemberAccess getMemberAccess(Map<String, Object> context) {
        return (MemberAccess) context.get(OgnlContext.MEMBER_ACCESS_CONTEXT_KEY);
    }

    /**
     * Sets the root object to use for all expressions in the given context - doesn't necessarily replace root object
     * instances explicitly passed in to other expression resolving methods on this class.
     * 
     * @param context The context to store the root object in.
     * @param root The root object.
     */
    public static void setRoot(Map<String, Object> context, Object root) {
        context.put(OgnlContext.ROOT_CONTEXT_KEY, root);
    }

    /**
     * Gets the stored root object for the given context - if any.
     * 
     * @param context The context to get the root object from.
     * @return The root object - or null if none found.
     */
    public static Object getRoot(Map<String, Object> context) {
        return context.get(OgnlContext.ROOT_CONTEXT_KEY);
    }

    /**
     * Gets the last {@link Evaluation} executed on the given context.
     * 
     * @param context The context to get the evaluation from.
     * @return The {@link Evaluation} - or null if none was found.
     */
    public static Evaluation getLastEvaluation(Map<String, Object> context) {
        return (Evaluation) context.get(OgnlContext.LAST_EVALUATION_CONTEXT_KEY);
    }

    /**
     * Evaluates the given OGNL expression tree to extract a value from the given root object. The default context is
     * set for the given context and root via <code>addDefaultContext()</code>.
     * 
     * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
     * @param context the naming context for the evaluation
     * @param root the root object for the OGNL expression
     * @return the result of evaluating the expression
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static <T> T getValue(Object tree, Map<String, Object> context, Object root) throws OgnlException {
        return Ognl.<T>getValue(tree, context, root, null);
    }

    /**
     * Evaluates the given OGNL expression tree to extract a value from the given root object. The default context is
     * set for the given context and root via <code>addDefaultContext()</code>.
     * 
     * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
     * @param context the naming context for the evaluation
     * @param root the root object for the OGNL expression
     * @param resultType the converted type of the resultant object, using the context's type converter
     * @return the result of evaluating the expression
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    @SuppressWarnings("unchecked") // will cause CCE if types are not compatible
    public static <T> T getValue(Object tree, Map<String, Object> context, Object root, Class<T> resultType)
            throws OgnlException {
        T result;
        OgnlContext ognlContext = (OgnlContext) addDefaultContext(root, context);

        Node node = (Node) tree;

        if (node.getAccessor() != null) {
            result = (T) node.getAccessor().get(ognlContext, root);
        } else {
            result = (T) node.getValue(ognlContext, root);
        }

        if (resultType != null) {
            result = getTypeConverter(context).convertValue(context, root, null, null, result, resultType);
        }
        return result;
    }

    /**
     * Gets the value represented by the given pre-compiled expression on the specified root object.
     * 
     * @param expression The pre-compiled expression, as found in {@link Node#getAccessor()}.
     * @param context The ognl context.
     * @param root The object to retrieve the expression value from.
     * @return The value.
     */
    @SuppressWarnings("unchecked") // will cause CCE if types are not compatible
    public static <T> T getValue(ExpressionAccessor expression, OgnlContext context, Object root) {
        return (T) expression.get(context, root);
    }

    /**
     * Gets the value represented by the given pre-compiled expression on the specified root object.
     * 
     * @param expression The pre-compiled expression, as found in {@link Node#getAccessor()}.
     * @param context The ognl context.
     * @param root The object to retrieve the expression value from.
     * @param resultType The desired object type that the return value should be converted to using the
     *            {@link #getTypeConverter(java.util.Map)} .
     * @return The value.
     */
    public static <T> T getValue(ExpressionAccessor expression, OgnlContext context, Object root,
            Class<T> resultType) throws OgnlException {
        return getTypeConverter(context).convertValue(context, root, null, null, expression.get(context, root),
                resultType);
    }

    /**
     * Evaluates the given OGNL expression to extract a value from the given root object in a given context
     * 
     * @see #parseExpression(String)
     * @see #getValue(Object,Object)
     * @param expression the OGNL expression to be parsed
     * @param context the naming context for the evaluation
     * @param root the root object for the OGNL expression
     * @return the result of evaluating the expression
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static <T> T getValue(String expression, Map<String, Object> context, Object root) throws OgnlException {
        return Ognl.<T>getValue(expression, context, root, null);
    }

    /**
     * Evaluates the given OGNL expression to extract a value from the given root object in a given context
     * 
     * @see #parseExpression(String)
     * @see #getValue(Object,Object)
     * @param expression the OGNL expression to be parsed
     * @param context the naming context for the evaluation
     * @param root the root object for the OGNL expression
     * @param resultType the converted type of the resultant object, using the context's type converter
     * @return the result of evaluating the expression
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static <T> T getValue(String expression, Map<String, Object> context, Object root, Class<T> resultType)
            throws OgnlException {
        return Ognl.<T>getValue(parseExpression(expression), context, root, resultType);
    }

    /**
     * Evaluates the given OGNL expression tree to extract a value from the given root object.
     * 
     * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
     * @param root the root object for the OGNL expression
     * @return the result of evaluating the expression
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static <T> T getValue(Object tree, Object root) throws OgnlException {
        return Ognl.<T>getValue(tree, root, null);
    }

    /**
     * Evaluates the given OGNL expression tree to extract a value from the given root object.
     * 
     * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
     * @param root the root object for the OGNL expression
     * @param resultType the converted type of the resultant object, using the context's type converter
     * @return the result of evaluating the expression
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static <T> T getValue(Object tree, Object root, Class<T> resultType) throws OgnlException {
        return Ognl.<T>getValue(tree, createDefaultContext(root), root, resultType);
    }

    /**
     * Convenience method that combines calls to <code> parseExpression </code> and <code> getValue</code>.
     * 
     * @see #parseExpression(String)
     * @see #getValue(Object,Object)
     * @param expression the OGNL expression to be parsed
     * @param root the root object for the OGNL expression
     * @return the result of evaluating the expression
     * @throws ExpressionSyntaxException if the expression is malformed
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static <T> T getValue(String expression, Object root) throws OgnlException {
        return Ognl.<T>getValue(expression, root, null);
    }

    /**
     * Convenience method that combines calls to <code> parseExpression </code> and <code> getValue</code>.
     * 
     * @see #parseExpression(String)
     * @see #getValue(Object,Object)
     * @param expression the OGNL expression to be parsed
     * @param root the root object for the OGNL expression
     * @param resultType the converted type of the resultant object, using the context's type converter
     * @return the result of evaluating the expression
     * @throws ExpressionSyntaxException if the expression is malformed
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static <T> T getValue(String expression, Object root, Class<T> resultType) throws OgnlException {
        return Ognl.<T>getValue(parseExpression(expression), root, resultType);
    }

    /**
     * Evaluates the given OGNL expression tree to insert a value into the object graph rooted at the given root object.
     * The default context is set for the given context and root via <code>addDefaultContext()</code>.
     * 
     * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
     * @param context the naming context for the evaluation
     * @param root the root object for the OGNL expression
     * @param value the value to insert into the object graph
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static void setValue(Object tree, Map<String, Object> context, Object root, Object value)
            throws OgnlException {
        OgnlContext ognlContext = (OgnlContext) addDefaultContext(root, context);
        Node n = (Node) tree;

        if (n.getAccessor() != null) {
            n.getAccessor().set(ognlContext, root, value);
            return;
        }

        n.setValue(ognlContext, root, value);
    }

    /**
     * Sets the value given using the pre-compiled expression on the specified root object.
     * 
     * @param expression The pre-compiled expression, as found in {@link Node#getAccessor()}.
     * @param context The ognl context.
     * @param root The object to set the expression value on.
     * @param value The value to set.
     */
    public static void setValue(ExpressionAccessor expression, OgnlContext context, Object root, Object value) {
        expression.set(context, root, value);
    }

    /**
     * Evaluates the given OGNL expression to insert a value into the object graph rooted at the given root object given
     * the context.
     * 
     * @param expression the OGNL expression to be parsed
     * @param root the root object for the OGNL expression
     * @param context the naming context for the evaluation
     * @param value the value to insert into the object graph
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static void setValue(String expression, Map<String, Object> context, Object root, Object value)
            throws OgnlException {
        setValue(parseExpression(expression), context, root, value);
    }

    /**
     * Evaluates the given OGNL expression tree to insert a value into the object graph rooted at the given root object.
     * 
     * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
     * @param root the root object for the OGNL expression
     * @param value the value to insert into the object graph
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static void setValue(Object tree, Object root, Object value) throws OgnlException {
        setValue(tree, createDefaultContext(root), root, value);
    }

    /**
     * Convenience method that combines calls to <code> parseExpression </code> and <code> setValue</code>.
     * 
     * @see #parseExpression(String)
     * @see #setValue(Object,Object,Object)
     * @param expression the OGNL expression to be parsed
     * @param root the root object for the OGNL expression
     * @param value the value to insert into the object graph
     * @throws ExpressionSyntaxException if the expression is malformed
     * @throws MethodFailedException if the expression called a method which failed
     * @throws NoSuchPropertyException if the expression referred to a nonexistent property
     * @throws InappropriateExpressionException if the expression can't be used in this context
     * @throws OgnlException if there is a pathological environmental problem
     */
    public static void setValue(String expression, Object root, Object value) throws OgnlException {
        setValue(parseExpression(expression), root, value);
    }

    /**
     * Checks if the specified {@link Node} instance represents a constant expression.
     * 
     * @param tree The {@link Node} to check.
     * @param context The context to use.
     * @return True if the node is a constant - false otherwise.
     * @throws OgnlException If an error occurs checking the expression.
     */
    public static boolean isConstant(Object tree, Map<String, Object> context) throws OgnlException {
        return ((SimpleNode) tree).isConstant((OgnlContext) addDefaultContext(null, context));
    }

    /**
     * Checks if the specified expression represents a constant expression.
     * 
     * @param expression The expression to check.
     * @param context The context to use.
     * @return True if the node is a constant - false otherwise.
     * @throws OgnlException If an error occurs checking the expression.
     */
    public static boolean isConstant(String expression, Map<String, Object> context) throws OgnlException {
        return isConstant(parseExpression(expression), context);
    }

    /**
     * Same as {@link #isConstant(Object, java.util.Map)} - only the {@link Map} context is created for you.
     * 
     * @param tree The {@link Node} to check.
     * @return True if the node represents a constant expression - false otherwise.
     * @throws OgnlException If an exception occurs.
     */
    public static boolean isConstant(Object tree) throws OgnlException {
        return isConstant(tree, createDefaultContext(null));
    }

    /**
     * Same as {@link #isConstant(String, java.util.Map)} - only the {@link Map} instance is created for you.
     * 
     * @param expression The expression to check.
     * @return True if the expression represents a constant - false otherwise.
     * @throws OgnlException If an exception occurs.
     */
    public static boolean isConstant(String expression) throws OgnlException {
        return isConstant(parseExpression(expression), createDefaultContext(null));
    }

    public static boolean isSimpleProperty(Object tree, Map<String, Object> context) throws OgnlException {
        return ((SimpleNode) tree).isSimpleProperty((OgnlContext) addDefaultContext(null, context));
    }

    public static boolean isSimpleProperty(String expression, Map<String, Object> context) throws OgnlException {
        return isSimpleProperty(parseExpression(expression), context);
    }

    public static boolean isSimpleProperty(Object tree) throws OgnlException {
        return isSimpleProperty(tree, createDefaultContext(null));
    }

    public static boolean isSimpleProperty(String expression) throws OgnlException {
        return isSimpleProperty(parseExpression(expression), createDefaultContext(null));
    }

    public static boolean isSimpleNavigationChain(Object tree, Map<String, Object> context) throws OgnlException {
        return ((SimpleNode) tree).isSimpleNavigationChain((OgnlContext) addDefaultContext(null, context));
    }

    public static boolean isSimpleNavigationChain(String expression, Map<String, Object> context)
            throws OgnlException {
        return isSimpleNavigationChain(parseExpression(expression), context);
    }

    public static boolean isSimpleNavigationChain(Object tree) throws OgnlException {
        return isSimpleNavigationChain(tree, createDefaultContext(null));
    }

    public static boolean isSimpleNavigationChain(String expression) throws OgnlException {
        return isSimpleNavigationChain(parseExpression(expression), createDefaultContext(null));
    }

    /** You can't make one of these. */
    private Ognl() {
    }
}