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 }