    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.jexl2;
    018
    019    import java.util.List;
    020    import java.util.Set;
    021    import java.util.concurrent.Callable;
    022
    023    import org.apache.commons.jexl2.parser.ASTJexlScript;
    024
    025    /**
    026     * Instances of ExpressionImpl are created by the {@link JexlEngine},
    027     * and this is the default implementation of the {@link Expression} and
    028     * {@link Script} interface.
    029     * @since 1.0
    030     */
    031    public class ExpressionImpl implements Expression, Script {
    032        /** The engine for this expression. */
    033        protected final JexlEngine jexl;
    034        /**
    035         * Original expression stripped from leading & trailing spaces.
    036         */
    037        protected final String expression;
    038        /**
    039         * The resulting AST we can interpret.
    040         */
    041        protected final ASTJexlScript script;
    042
    043        /**
    044         * Do not let this be generally instantiated with a 'new'.
    045         *
    046         * @param engine the interpreter to evaluate the expression
    047         * @param expr the expression.
    048         * @param ref the parsed expression.
    049         */
    050        protected ExpressionImpl(JexlEngine engine, String expr, ASTJexlScript ref) {
    051            jexl = engine;
    052            expression = expr;
    053            script = ref;
    054        }
    055
    056        /**
    057         * {@inheritDoc}
    058         */
    059        public Object evaluate(JexlContext context) {
    060            if (script.jjtGetNumChildren() < 1) {
    061                return null;
    062            }
    063            Interpreter interpreter = jexl.createInterpreter(context);
    064            interpreter.setFrame(script.createFrame((Object[]) null));
    065            return interpreter.interpret(script.jjtGetChild(0));
    066        }
    067
    068        /**
    069         * {@inheritDoc}
    070         */
    071        public String dump() {
    072            Debugger debug = new Debugger();
    073            boolean d = debug.debug(script);
    074            return debug.data() + (d ? " /*" + debug.start() + ":" + debug.end() + "*/" : "/*?:?*/ ");
    075        }
    076
    077        /**
    078         * {@inheritDoc}
    079         */
    080        public String getExpression() {
    081            return expression;
    082        }
    083
    084        /**
    085         * Provide a string representation of this expression.
    086         * @return the expression or blank if it's null.
    087         */
    088        @Override
    089        public String toString() {
    090            String expr = getExpression();
    091            return expr == null ? "" : expr;
    092        }
    093
    094        /**
    095         * {@inheritDoc}
    096         */
    097        public String getText() {
    098            return toString();
    099        }
    100
    101        /**
    102         * {@inheritDoc}
    103         */
    104        public Object execute(JexlContext context) {
    105            Interpreter interpreter = jexl.createInterpreter(context);
    106            interpreter.setFrame(script.createFrame((Object[]) null));
    107            return interpreter.interpret(script);
    108        }
    109
    110        /**
    111         * {@inheritDoc}
    112         * @since 2.1
    113         */
    114        public Object execute(JexlContext context, Object... args) {
    115            Interpreter interpreter = jexl.createInterpreter(context);
    116            interpreter.setFrame(script.createFrame(args));
    117            return interpreter.interpret(script);
    118        }
    119
    120        /**
    121         * {@inheritDoc}
    122         * @since 2.1
    123         */
    124        public String[] getParameters() {
    125            return script.getParameters();
    126        }
    127
    128        /**
    129         * {@inheritDoc}
    130         * @since 2.1
    131         */
    132        public String[] getLocalVariables() {
    133            return script.getLocalVariables();
    134        }
    135
    136        /**
    137         * {@inheritDoc}
    138         * @since 2.1
    139         */
    140        public Set<List<String>> getVariables() {
    141            return jexl.getVariables(this);
    142        }
    143
    144        /**
    145         * {@inheritDoc}
    146         * @since 2.1
    147         */
    148        public Callable<Object> callable(JexlContext context) {
    149            return callable(context, (Object[]) null);
    150        }
    151
    152        /**
    153         * {@inheritDoc}
    154         * @since 2.1
    155         */
    156        public Callable<Object> callable(JexlContext context, Object... args) {
    157            final Interpreter interpreter = jexl.createInterpreter(context);
    158            interpreter.setFrame(script.createFrame(args));
    159
    160            return new Callable<Object>() {
    161                /** Use interpreter as marker for not having run. */
    162                private Object result = interpreter;
    163
    164                public Object call() throws Exception {
    165                    if (result == interpreter) {
    166                        result = interpreter.interpret(script);
    167                    }
    168                    return result;
    169                }
    170
    171            };
    172        }
    173
    174    }