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 }