/*
* Copyright (C) 2004 TiongHiang Lee
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Email: thlee@onemindsoft.org
*/
package org.onemind.jxp;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.onemind.commons.invoke.InvocableFunction;
import org.onemind.commons.java.datastructure.NametableStack;
import org.onemind.commons.java.datastructure.ThreadLocalStack;
import org.onemind.commons.java.lang.reflect.ReflectUtils;
import org.onemind.commons.java.util.*;
import org.onemind.jxp.parser.*;
import org.onemind.jxp.util.StaticImport;
import org.onemind.jxp.util.StaticImportUtils;
/**
* The jxp processor
* @author TiongHiang Lee (thlee@onemindsoft.org)
*
*/
public class JxpProcessor implements JxpParserVisitor
{
/** the logger * */
private static final Logger _logger = Logger.getLogger(JxpProcessor.class.getName());
/** represent ONE * */
private static final Integer ONE = new Integer(1);
/** contains zero values for primitive **/
private static final Map PRIMITIVE_DEFAULTS = new HashMap();
static
{
PRIMITIVE_DEFAULTS.put(Integer.TYPE, new Integer(0));
PRIMITIVE_DEFAULTS.put(Long.TYPE, new Long(0));
PRIMITIVE_DEFAULTS.put(Float.TYPE, new Float(0));
PRIMITIVE_DEFAULTS.put(Double.TYPE, new Double(0));
PRIMITIVE_DEFAULTS.put(Character.TYPE, new Character((char) 0));
PRIMITIVE_DEFAULTS.put(Byte.TYPE, new Byte((byte) 0));
PRIMITIVE_DEFAULTS.put(Boolean.TYPE, Boolean.FALSE);
}
/**
* process a file
* @param args the arguments
* @throws Exception if exception
*/
public static void main(String[] args) throws Exception
{
if (args.length != 2)
{
System.out.println("Usage: java org.onemind.jxp.JxpProcessor <source dir> <page>");
} else
{
FilePageSource source = new FilePageSource(args[0]);
JxpContext context = new JxpContext(source);
JxpProcessor processor = new JxpProcessor(context);
Writer writer = new OutputStreamWriter(System.out);
try
{
processor.process(args[1], writer, Collections.EMPTY_MAP);
} catch (Exception e)
{
e.printStackTrace();
}
writer.flush();
}
}
/**
* Represents a user defined function
* @author TiongHiang Lee (thlee@onemindsoft.org)
*
*/
private class JxpUserDefinedFunction
{
/** the declarator **/
private SimpleNode _paramSpec;
/** the block **/
private AstBlock _block;
/**
* Constructor
* @param dec the declarator
* @param block the function block
*/
public JxpUserDefinedFunction(SimpleNode paramSpec, AstBlock block)
{
_paramSpec = paramSpec;
_block = block;
}
/**
* Get the declarator
* @return the declarator
*/
public SimpleNode getParameterSpec()
{
return _paramSpec;
}
/**
* Get the block
* @return the block
*/
public AstBlock getBlock()
{
return _block;
}
}
/** a context local keep tracks of current processing context * */
private ThreadLocalStack _contextLocal = new ThreadLocalStack();
/** the jxp page source * */
private JxpContext _context;
/** whether do method status **/
//TODO: add as config options
private boolean doMethodStats;
/** whether to check function argument type **/
private boolean _checkFunctionArgumentType = false;
/** the method statistic counter **/
private final Counter _methodStats = new Counter();
/**
* Constructor
* @param source the page source
*/
public JxpProcessor(JxpContext context)
{
_context = context;
}
/**
* Get the source
* @return the source
*/
public final JxpContext getContext()
{
return _context;
}
/**
* Assign the value assignable target node to the value
* @param node the assignable target
* @param value the value to assign
* @return the value assinged
* @throws ProcessingException if the node is not an assignable
*/
protected Object assign(SimpleNode node, Object value) throws ProcessingException
{
Object target = resolveAssignmentTarget(node, true);
if (target instanceof Assignable)
{
return ((Assignable) target).assign(value);
} else
{
return generateProcessingException(new IllegalArgumentException(node + " is not assignable"), node);
}
}
/**
* Assign a variable in a current nametable stack to the value
* @param name the variable name
* @param value the value
* @return the value assigned
*/
protected Object assignVariable(String name, Object value)
{
NametableStack ntStack = getCurrentContext().getNametableStack();
ntStack.assign(name, value);
return value;
}
/**
* Call the function of the processor. Call predefined print or println if the method name matched. Otherwise, reflection will
* be used on the processor to invoke method
* @param methodName the method name
* @param args the arguments
* @return the value returned by the method call
* @throws Exception if there's problem calling method
*/
protected Object callFunction(String methodName, Object[] args) throws Exception
{
//built-in functions
if (methodName.equals("print"))
{
print(args[0]);
return null;
} else if (methodName.equals("println"))
{
println(args[0]);
return null;
} else if (methodName.equals("getJxpEnvironment")){
return getEnvironment();
} else
{
JxpProcessingContext context = getCurrentContext();
String functionName = methodName;
if (context.getUserDefinedFunctions().containsKey(functionName))
{
JxpUserDefinedFunction function = (JxpUserDefinedFunction) context.getUserDefinedFunctions().get(functionName);
NametableStack nt = context.getNametableStack();
int scope = nt.newLocalScope();
declareFunctionLocals(functionName, function.getParameterSpec(), args);
try
{
Object obj = function.getBlock().jjtAccept(this, null);
if (obj == Control.EXIT)
{
return obj;
} else if (obj instanceof Control) //return value
{
return ((Control) obj).getObject();
} else
{
return obj;
}
} finally
{
nt.closeLocalScope(scope);
}
} else
{
//try static import
List staticImports = context.getStaticImports();
Iterator it = staticImports.iterator();
while (it.hasNext())
{
StaticImport sImport = (StaticImport) it.next();
InvocableFunction func = sImport.getFunction(functionName, args);
if (func != null)
{
return func.invoke(null, args);
}
}
//lastly, throw exception
throw new NoSuchMethodException("Method " + methodName + " not found for the Processor");
}
}
}
/**
* Create the function environment
* @param params the parameters
* @param args the arguments
*/
public void declareFunctionLocals(String functionName, SimpleNode params, Object[] args) throws Exception
{
NametableStack ntStack = getCurrentContext().getNametableStack();
int n = params.jjtGetNumChildren();
Map defaults = new HashMap();
for (int i = 0; i < args.length; i++)
{
if (args[i] instanceof AstNamedArgument)
{
SimpleNode arg = (SimpleNode) args[i];
Object value = arg.jjtGetChild(0).jjtAccept(this, null);
defaults.put(arg.getData(), value);
}
}
if (params instanceof AstFormalParameters)
{
for (int i = 0; i < n; i++)
{
AstFormalParameter param = (AstFormalParameter) params.jjtGetChild(i);
AstVariableDeclaratorId id = (AstVariableDeclaratorId) param.jjtGetChild(1);
AstType type = (AstType) param.jjtGetChild(0);
Class paramType = (Class) type.jjtAccept(this, null);
if (param.jjtGetNumChildren() == 2)
{//no defaults
if (args.length <= i)
{
throw new IllegalArgumentException("Mismatch number of arguments");
} else if (args[i] instanceof AstNamedArgument)
{
throw new IllegalArgumentException("Expecting required paramater "
+ id.getData() + " for function " + functionName);
} else
{
if (_checkFunctionArgumentType)
{//do type checking
if (paramType.isPrimitive())
{
if (args[i] == null)
{
throw new IllegalArgumentException("Primitive argument " + id.getData() + " cannot be null");
} else if (!ReflectUtils.isPrimitiveInstance(paramType, args[i]))
{
throw new IllegalArgumentException("Mismatch argument type for " + id.getData() + ". Expecting "
+ paramType.getName());
}
} else if (args[i] != null)
{
if (!paramType.isInstance(args[i]))
{
throw new IllegalArgumentException("Mismatch argument type for " + id.getData()
+ ". Expecting " + paramType.getName());
}
}
}
ntStack.declare((String) id.getData(), args[i]);
}
} else
{//has default
if (defaults.containsKey(id.getData()))
{
Object value = defaults.remove(id.getData());
ntStack.declare((String) id.getData(), value);
} else
{
if (i >= args.length || args[i] instanceof AstNamedArgument)
{
Object value = param.jjtGetChild(2).jjtAccept(this, null);
ntStack.declare((String) id.getData(), value);
} else
{
ntStack.declare((String) id.getData(), args[i]);
}
}
}
}
if (defaults.size() > 0)
{
throw new IllegalArgumentException("Unknown default " + defaults + " for function " + functionName);
}
} else
{//assume variable parameters (varargs)
ntStack.declare((String) params.getData(), args);
}
}
/**
* Throws the exception
* @param e the throwable
* @param node the node that the exception current
* @return will not return since exception will always be thrown
*/
private ProcessingException generateProcessingException(Throwable e, SimpleNode node)
{
ProcessingException ex = new ProcessingException(getCurrentContext().getCurrentPage(), e, node);
return ex;
}
/**
* Include another page as a part of current page and process it
* @param id the id
* @return the object
* @throws Exception if there's exception
*/
protected Object includeCall(String id) throws Exception
{
return process(id, getCurrentContext());
}
/**
* Instantiate an instance of class type using the arguments
* @param type the type to instantiate
* @param args the arguments
* @return the object instantiated
* @throws Exception if there's problem in the instantiation
*/
protected Object instantiate(Class type, Object[] args) throws Exception
{
if (_logger.isLoggable(Level.FINEST))
{
_logger.finest("Instantiaing " + type + " with " + StringUtils.concat(args, ","));
}
return ReflectUtils.newInstance(type, args);
}
/**
* Invoke the method of object obj with given argument
* @param obj the object
* @param methodName the method name
* @param args the arguments
* @return the value return by the method invoked
* @throws Exception if there's problem invoking the method
*/
protected Object invokeMethod(Object obj, String methodName, Object[] args) throws Exception
{
if (_logger.isLoggable(Level.FINEST))
{
_logger.finest("Invoking " + obj.getClass() + "." + methodName + "(" + StringUtils.concat(args, ",") + ")");
}
if (obj == this)
{
return callFunction(methodName, args);
} else
{
if (doMethodStats)
{
_methodStats.count(methodName);
}
if (obj instanceof JxpInvocable)
{
JxpInvocable invocable = (JxpInvocable) obj;
if (invocable.canInvoke(methodName, args))
{
return invocable.invoke(methodName, args);
}
} //else fall through
return ReflectUtils.invoke(obj, methodName, args);
}
}
/**
* Look up a variable in current nametable stack
* @param variableName the variable name
* @return the value of the variable
* @throws NoSuchFieldException the the variable cannot be found
*/
protected Object lookupVariable(String variableName) throws NoSuchFieldException
{
NametableStack ntStack = getCurrentContext().getNametableStack();
if (!ntStack.containsName(variableName))
{
throw new NoSuchFieldException("Variable/Function " + variableName + " is not declared before");
}
Object v = ntStack.access(variableName);
if (_logger.isLoggable(Level.FINEST))
{
_logger.finest("Looking up variable " + variableName + " found " + v);
}
return v;
}
/**
* print the object by printing o.toString() using writer of current context. If the object is null, "null" will be printed.
* @param o the object
* @throws IOException if there's problem doing the printing
*/
protected void print(Object o) throws IOException
{
if (o == null)
{
print("null");
} else
{
print(o.toString());
}
}
/**
* Print the string using writer of current context
* @param s the string
* @throws IOException if there's io problem TODO: make to flag IOException to avoid call writes again
*/
protected void print(String s) throws IOException
{
Writer writer = getCurrentContext().getWriter();
try
{
writer.write(s);
} catch (Exception e)
{
_logger.throwing(getClass().getName(), "print", e);
}
}
/**
* print the object with the line delimiter "\n"
* @param o the object
* @throws IOException if there's problem doing the printing
*/
protected void println(Object o) throws IOException
{
print(o + "\n");
}
/**
* print the object with the line delimiter "\n"
* @param s the string
* @throws IOException if there's problem doing the printing
*/
protected void println(String s) throws IOException
{
print(s + "\n");
}
/**
* Process a page with empty environment
*/
public Object process(String id, Writer writer) throws Exception
{
return process(id, writer, Collections.EMPTY_MAP);
}
/**
* process the page identified by id with the context given
* @param id the id
* @param env the environment
* @return value return by this page
* @throws Exception if there's problem doing the printing
*/
public Object process(String id, Writer writer, Map env) throws Exception
{
JxpProcessingContext procContext = _context.createProcessingContext(env, writer);
int scope = _contextLocal.pushLocal(procContext);
try
{
return process(id, procContext);
} finally
{
_contextLocal.popLocalUtil(scope);
}
}
/**
* Processing a page identified by id in current context
* @param id the id
* @return the value return by the processing
* @throws Exception if there's problem doing the printing
*/
protected Object process(String id, JxpProcessingContext context) throws Exception
{
//resolve the actual id
String scriptId = id;
JxpPage currentPage = context.getCurrentPage();
if (currentPage != null && !id.startsWith("/")) //relative path
{
String prefix = StringUtils.substringBeforeLast(currentPage.getName(), "/");
if (prefix != null)
{
scriptId = FileUtils.concatFilePath(prefix, id);
}
}
JxpPage page = _context.getPageSource().getJxpPage(scriptId);
try
{
context.pushPage(page);
return visit(page.getJxpDocument(), null);
} finally
{
context.popPage(page);
}
}
/**
* Get the current processing context
* @return the current processing context
*/
public JxpProcessingContext getCurrentContext()
{
return (JxpProcessingContext) _contextLocal.getLocal();
}
/**
* Process a page identified by id in current context
* @param id the id
* @return the value return by the page
* @throws Exception if there's problem doing the printing
*/
protected Object processCall(String id) throws Exception
{
JxpProcessingContext context = getCurrentContext();
int scope = context.getNametableStack().newScope();
try
{
return process(id, context);
} finally
{
context.getNametableStack().closeScope(scope);
}
}
/**
* Resolve the arguments for function or method call
* @param node the node
* @param context the context
* @return object array containing the resolved argument values
* @throws Exception if there's problem
*/
protected Object[] resolveArguments(AstArguments node, JxpProcessingContext context) throws Exception
{
int n = node.jjtGetNumChildren();
Object[] args = new Object[n];
for (int i = 0; i < n; i++)
{
args[i] = node.jjtGetChild(i).jjtAccept(this, context);
}
return args;
}
/**
* Resolve the array dimensions needed
* @param node the ArrayDims node
* @param context the processing context
* @return the int array containing the dimensions info
* @throws Exception if there's problem resolving the dimension
*/
protected int[] resolveArrayDims(AstArrayDims node, JxpProcessingContext context) throws Exception
{
int[] dims = new int[node.jjtGetNumChildren()];
for (int i = 0; i < node.jjtGetNumChildren(); i++)
{
Object o = node.jjtGetChild(i).jjtAccept(this, context);
if (o instanceof Number)
{
dims[i] = ((Number) o).intValue();
} else
{
throw generateProcessingException(new IllegalArgumentException("Array dimension " + o + " is not a number"), node);
}
}
return dims;
}
/**
* Resolve the assignment target. Exception will be thrown if the node is not assignable and throwExcpetion is true. Otherwise
* null will be return if the node cannot be resolved to assignment target.
* @param node the simple node or the target
* @param throwException whether to throw exception
* @return the target
* @throws ProcessingException if the target cannot be resolved
*/
protected Assignable resolveAssignmentTarget(SimpleNode node, boolean throwException) throws ProcessingException
{
if (node instanceof AstName)
{
AstName name = (AstName) node;
List l = (List) name.getData();
JxpProcessingContext context = getCurrentContext();
if (l.size() == 1)
{
String variableName = (String) l.get(0);
// first case
if (context.getNametableStack().containsName(variableName))
{
return new VariableAssignable((String) l.get(0), context);
} else
{
//second case
JxpPage page = context.getCurrentPage();
if (page.hasStaticVariable(variableName))
{
return new StaticVariableAssignable((String) l.get(0), page);
}
throw generateProcessingException(new IllegalArgumentException("Variable " + variableName
+ " has not been declared."), node);
}
} else
{
//TODO: how about assigning to a field? arr
if (throwException)
{
throw generateProcessingException(new IllegalArgumentException(node + " is not assignable"), node);
} else
{
return null;
}
}
} else if (node instanceof AstArrayReference)
{
try
{
Object obj = node.jjtGetChild(0).jjtAccept(this, null);
if (obj == null)
{
throw generateProcessingException(new NullPointerException(), (SimpleNode) node.jjtGetChild(0));
}
if (!obj.getClass().isArray())
{
throw generateProcessingException(new IllegalArgumentException("Argument is not an array"), (SimpleNode) node
.jjtGetChild(0));
}
Object dimObj = node.jjtGetChild(1).jjtAccept(this, null);
int dim = 0;
if (dimObj instanceof Number)
{
dim = ((Number) dimObj).intValue();
} else
{
throw generateProcessingException(new IllegalArgumentException("Invalid index type " + dimObj.getClass()
+ " for array"), node);
}
return new ArrayAssignable(obj, dim);
} catch (ProcessingException e)
{
throw (ProcessingException) e;
} catch (Exception e)
{
throw generateProcessingException(e, node);
}
} else
{ //TODO: other kind of assignable such as array etc
if (throwException)
{
throw generateProcessingException(new IllegalArgumentException(node + " is not assignable"), node);
} else
{
return null;
}
}
}
/**
* Resolve the class. Call the current context for resolving since the imports in context specific
* @param className the class name
* @return the class
*/
protected final Class resolveClass(String className)
{
return getCurrentContext().resolveClass(className);
}
/**
* Resolve the field on and object. Also resolve the array length field
* @param obj the object
* @param fieldName the field name
* @return the field value
* @throws Exception if the field cannot be resolved
*/
protected Object resolveField(Object obj, String fieldName) throws Exception
{
if (_logger.isLoggable(Level.FINEST))
{
_logger.finest("Resolving field " + fieldName + " of " + obj);
}
if (obj == null)
{
throw new NoSuchFieldException("Cannot find field " + fieldName + " for null");
}
if (fieldName.equals("class"))
{
if (obj instanceof Class)
{
return (Class) obj;
} else
{
throw new IllegalStateException(".class cannot be apply to " + obj);
}
}
if (fieldName.equals("length"))
{ //check if is array
if (obj.getClass().isArray())
{
return new Integer(Array.getLength(obj));
} //otherwise just pass through
}
if (obj instanceof JxpInvocable)
{
JxpInvocable invocable = (JxpInvocable) obj;
if (invocable.canInvoke(fieldName, null))
{
return invocable.invoke(fieldName, null);
}
}
if (obj instanceof Map)
{
return ((Map) obj).get(fieldName);
} //otherwise just pass through to use reflection
Field f = null;
if (obj instanceof Class)
{
f = ((Class) obj).getField(fieldName);
} else
{
f = obj.getClass().getField(fieldName);
}
return f.get(obj);
}
/**
* Resolve a object given the name in current processing context. It cound be variable, or class
* @param l containing series of identifier
* @return the object associated with the name
* @throws Exception if there's problem resolving the name
*/
protected Object resolveName(List l) throws Exception
{
Object current = null;
JxpProcessingContext context = getCurrentContext();
NametableStack ntStack = context.getNametableStack();
for (int i = 0; i < l.size(); i++)
{
String s = (String) l.get(i);
if (i == 0)
{
//first case, variable
if (ntStack.containsName(s))
{
current = ntStack.access(s); //lookup variable
} else
{//second case, page static
JxpPage page = context.getCurrentPage();
if (page.hasStaticVariable(s))
{
current = page.getStaticVariable(s);
} else
{
//third case, resolve class
current = resolveClass(s);
if (current == null)
{
throw new NoSuchFieldException("Variable " + s + " has not been declared");
}
}
}
} else
{
current = resolveField(current, s);
}
}
return current;
}
/**
* Concat the ASTName to a dotted name notation
* @param name the ASTName object
* @return the dotted name string
*/
private String toDottedName(AstName name)
{
return StringUtils.concat((List) name.getData(), ".");
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArguments, java.lang.Object)
*/
public Object visit(AstArguments node, Object data) throws Exception
{
throw new IllegalStateException("visit(AstArguments, Object) should not be called");
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArrayAllocationExpression, java.lang.Object)
*/
public Object visit(AstArrayAllocationExpression node, Object data) throws Exception
{
String className = toDottedName((AstName) node.jjtGetChild(0));
Class type = resolveClass(className);
if (type == null)
{
throw generateProcessingException(new ClassNotFoundException("No definition found for " + className), node);
}
SimpleNode n = (SimpleNode) node.jjtGetChild(1);
if (n instanceof AstArrayDims)
{
int[] dims = resolveArrayDims((AstArrayDims) n, getCurrentContext());
return Array.newInstance(type, dims);
} else
{ //must be ArrayInitializer
return n.jjtAccept(this, type);
}
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArrayDims, java.lang.Object)
*/
public Object visit(AstArrayDims node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException("AstArrayDims are not supposed to be called"), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArrayInitializer, java.lang.Object)
*/
public Object visit(AstArrayInitializer node, Object data) throws Exception
{
Class type = (data instanceof Class) ? (Class) data : Object.class;
int dim = node.jjtGetNumChildren();
List l = new ArrayList();
Class elementType = null;
for (int i = 0; i < dim; i++)
{
Object element = node.jjtGetChild(i).jjtAccept(this, type);
//make sure the element type is correct
if (element != null)
{
elementType = element.getClass(); //save for latter
if (!elementType.isArray())
{//must be primitive - check it
if (!type.isAssignableFrom(element.getClass()))
{
throw generateProcessingException(new IllegalArgumentException("Illegal element " + element + " in "
+ type.getName() + " array"), (SimpleNode) node.jjtGetChild(i));
}
}
} else
{
if (type.isPrimitive())
{
throw generateProcessingException(new IllegalArgumentException("Illegal element " + element + " in "
+ type.getName() + " array"), (SimpleNode) node.jjtGetChild(i));
}
}
l.add(element);
}
if (elementType != null)
{
Object[] array = (Object[]) Array.newInstance(elementType, l.size());
return l.toArray(array);
} else
{
return l.toArray();
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstArrayReference, java.lang.Object)
*/
public Object visit(AstArrayReference node, Object data) throws Exception
{
Object obj = node.jjtGetChild(0).jjtAccept(this, data);
if (obj != null && obj.getClass().isArray())
{
Object dimObj = node.jjtGetChild(1).jjtAccept(this, data);
int dim = 0;
if (dimObj instanceof Number)
{
dim = ((Number) dimObj).intValue();
} else
{
throw generateProcessingException(new IllegalArgumentException("Invalid index type " + dimObj.getClass()
+ " for array"), node);
}
if (_logger.isLoggable(Level.FINEST))
{
_logger.finest("Resolving array reference of " + obj + "[" + dim + "]");
}
return Array.get(obj, dim);
} else
{
throw generateProcessingException(new IllegalArgumentException("Cannot get array referernce of non-array " + obj), node);
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstAssertStatement, java.lang.Object)
*/
public Object visit(AstAssertStatement node, Object data) throws Exception
{
for (int i = 0; i < node.jjtGetNumChildren(); i++)
{
Boolean assertion = Evaluator.toBoolean(node.jjtGetChild(i).jjtAccept(this, data));
if (!assertion.booleanValue())
{
throw generateProcessingException(new AssertionError("Assertion error "), (SimpleNode) node.jjtGetChild(i));
}
}
return Boolean.TRUE;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstAssignExpression, java.lang.Object)
*/
public Object visit(AstAssignExpression node, Object data) throws Exception
{
Object value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), value);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstAndAssignExpression, java.lang.Object)
*/
public Object visit(AstBitwiseAndAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.bitwiseAnd(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBitAndExpression, java.lang.Object)
*/
public Object visit(AstBitwiseAndExpression node, Object data) throws Exception
{
return Evaluator.bitwiseAnd(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstTildeUnaryExpression, java.lang.Object)
*/
public Object visit(AstBitwiseComplementExpression node, Object data) throws Exception
{
return Evaluator.bitwiseComplement(node.jjtGetChild(0).jjtAccept(this, data));
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBitwiseOrAssignExpression, java.lang.Object)
*/
public Object visit(AstBitwiseOrAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.bitwiseOr(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstInclusiveOrExpression, java.lang.Object)
*/
public Object visit(AstBitwiseOrExpression node, Object data) throws Exception
{
return Evaluator.bitwiseOr(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBitwiseXOrAssignExpression, java.lang.Object)
*/
public Object visit(AstBitwiseXOrAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.bitwiseXOr(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstExclusiveOrExpression, java.lang.Object)
*/
public Object visit(AstBitwiseXOrExpression node, Object data) throws Exception
{
return Evaluator.bitwiseXOr(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBlock, java.lang.Object)
*/
public Object visit(AstBlock node, Object data) throws Exception
{
JxpProcessingContext context = getCurrentContext();
int scope = context.getNametableStack().newScope();
Object obj = null;
SimpleNode childNode = null;
int i = 0;
try
{
for (i = 0; i < node.jjtGetNumChildren(); i++)
{
childNode = (SimpleNode) node.jjtGetChild(i);
obj = childNode.jjtAccept(this, data);
if (obj instanceof Control)
{
break;
}
}
} catch (ProcessingException pe)
{
throw pe;
} catch (Exception e)
{
throw generateProcessingException(e, childNode);
} finally
{
context.getNametableStack().closeScope(scope);
}
return obj;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBreakStatement, java.lang.Object)
*/
public Object visit(AstBreakStatement node, Object data) throws Exception
{
return Control.BREAK;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstCase, java.lang.Object)
*/
public Object visit(AstCase node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException("Switch case: are not suppossed to be called"), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstCastExpression, java.lang.Object)
*/
public Object visit(AstCastExpression node, Object data) throws Exception
{
return node.jjtGetChild( 1 ).jjtAccept( this, data );
}
/**
* {@inheritDoc}
*/
public Object visit(AstCatchBlock node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException("This should not be called"), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstConditionalAndExpression, java.lang.Object)
*/
public Object visit(AstConditionalAndExpression node, Object data) throws Exception
{
Boolean b1 = Evaluator.toBoolean(node.jjtGetChild(0).jjtAccept(this, data));
if (!b1.booleanValue())
{
return Boolean.FALSE;
}
Boolean b2 = Evaluator.toBoolean(node.jjtGetChild(1).jjtAccept(this, data));
if (!b2.booleanValue())
{
return Boolean.FALSE;
} else
{
return Boolean.TRUE;
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstConditionalOrExpression, java.lang.Object)
*/
public Object visit(AstConditionalOrExpression node, Object data) throws Exception
{
Boolean b1 = Evaluator.toBoolean(node.jjtGetChild(0).jjtAccept(this, data));
if (b1.booleanValue())
{
return Boolean.TRUE;
}
Boolean b2 = Evaluator.toBoolean(node.jjtGetChild(1).jjtAccept(this, data));
if (b2.booleanValue())
{
return Boolean.TRUE;
} else
{
return Boolean.FALSE;
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstContent, java.lang.Object)
*/
public Object visit(AstContent node, Object data) throws Exception
{
Object content = node.getData();
print(content);
return content;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstContinueStatement, java.lang.Object)
*/
public Object visit(AstContinueStatement node, Object data) throws Exception
{
return Control.CONTINUE;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstSlashAssignExpression, java.lang.Object)
*/
public Object visit(AstDivideAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.divide(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstSlashExpression, java.lang.Object)
*/
public Object visit(AstDivideExpression node, Object data) throws Exception
{
return Evaluator.divide(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstDoStatement, java.lang.Object)
*/
public Object visit(AstDoStatement node, Object data) throws Exception
{
Node condition = node.jjtGetChild(1);
Boolean b = null;
Object returnValue = null;
do
{
returnValue = node.jjtGetChild(0).jjtAccept(this, data);
if (returnValue instanceof Control)
{
if (returnValue == Control.CONTINUE)
{
returnValue = null;
} else if (returnValue == Control.BREAK)
{
returnValue = null;
break;
} else
{ //must be return w/wo object
break;
}
}
b = Evaluator.toBoolean(condition.jjtAccept(this, data));
} while (b.booleanValue());
return returnValue;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstEmptyStatement, java.lang.Object)
*/
public Object visit(AstEmptyStatement node, Object data) throws Exception
{
return null;
}
/**
* @see org.onemind.jxp.parser.JxpParserVisitor#visit(jxp.parser.AstEQExpression, java.lang.Object)
*/
public Object visit(AstEQExpression node, Object data) throws Exception
{
Object o1 = node.jjtGetChild(0).jjtAccept(this, data), o2 = node.jjtGetChild(1).jjtAccept(this, data);
return Evaluator.eq(o1, o2);
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstField, java.lang.Object)
*/
public Object visit(AstField node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException("visit(AstField, Object) is not supposed to be called"), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstFieldDeclaration, java.lang.Object)
*/
public Object visit(AstFieldDeclaration node, Object data) throws Exception
{
Boolean isStatic = (node.getData() == null) ? Boolean.FALSE : Boolean.TRUE;
Object[] passOn = new Object[]{node.jjtGetChild(0), isStatic};
//ignore the type
for (int i = 1; i < node.jjtGetNumChildren(); i++)
{
node.jjtGetChild(i).jjtAccept(this, passOn);
}
return null;
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstFieldReference, java.lang.Object)
*/
public Object visit(AstFieldReference node, Object data) throws Exception
{
Object o1 = node.jjtGetChild(0).jjtAccept(this, data);
String fieldName = (String) ((SimpleNode) node.jjtGetChild(1)).getData();
return resolveField(o1, fieldName);
}
/**
* {@inheritDoc}
*/
public Object visit(AstFinallyBlock node, Object data) throws Exception
{
return node.jjtGetChild(0).jjtAccept(this, data);
//pass on
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstForInit, java.lang.Object)
*/
public Object visit(AstForInit node, Object data) throws Exception
{
return node.childrenAccept(this, data);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstFormalParameter, java.lang.Object)
*/
public Object visit(AstFormalParameter node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException(
"visit(AstFormalParameter, Object) are not supposed to be called"), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstFormalParameters, java.lang.Object)
*/
public Object visit(AstFormalParameters node, Object data) throws Exception
{
throw generateProcessingException(new UnsupportedOperationException("Unsupported Language Feature"), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstForStatement, java.lang.Object)
*/
public Object visit(AstForStatement node, Object data) throws Exception
{
JxpProcessingContext context = getCurrentContext();
SimpleNode forInit = null, forCondition = null, forUpdate = null, statements = null;
for (int i = 0; i < node.jjtGetNumChildren() - 1; i++)
{
SimpleNode n = (SimpleNode) node.jjtGetChild(i);
if (n instanceof AstForInit)
{
forInit = n;
} else if (n instanceof AstForUpdate)
{
forUpdate = n;
} else
{
forCondition = n;
}
}
statements = (SimpleNode) node.jjtGetChild(node.jjtGetNumChildren() - 1);
int newscope = context.getNametableStack().newScope(); //this must be in front of for init
if (forInit != null)
{
forInit.jjtAccept(this, data);
}
Boolean condition = Boolean.TRUE;
if (forCondition != null)
{
condition = Evaluator.toBoolean(forCondition.jjtAccept(this, data));
}
Object returnValue = null;
try
{
while (condition.booleanValue())
{
returnValue = statements.jjtAccept(this, data);
if (returnValue == Control.CONTINUE)
{
returnValue = null;
//let it pass
} else if (returnValue == Control.BREAK)
{
returnValue = null;
break;
} else if (returnValue instanceof Control)
{ //must be return w/wo object
break;
}
if (forUpdate != null)
{
forUpdate.jjtAccept(this, data);
}
if (forCondition != null)
{
condition = Evaluator.toBoolean(forCondition.jjtAccept(this, data));
}
}
} finally
{
context.getNametableStack().closeScope(newscope);
}
return returnValue;
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstForUpdate, java.lang.Object)
*/
public Object visit(AstForUpdate node, Object data) throws Exception
{
return node.childrenAccept(this, data);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstGEExpression, java.lang.Object)
*/
public Object visit(AstGEExpression node, Object data) throws Exception
{
Object o1 = node.jjtGetChild(0).jjtAccept(this, data), o2 = node.jjtGetChild(1).jjtAccept(this, data);
return Evaluator.ge(o1, o2);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstGTExpression, java.lang.Object)
*/
public Object visit(AstGTExpression node, Object data) throws Exception
{
Object o1 = node.jjtGetChild(0).jjtAccept(this, data), o2 = node.jjtGetChild(1).jjtAccept(this, data);
return Evaluator.gt(o1, o2);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstHookExpression, java.lang.Object)
*/
public Object visit(AstHookExpression node, Object data) throws Exception
{
Object returnValue = node.jjtGetChild(0).jjtAccept(this, data);
if (returnValue instanceof Boolean)
{
if (Boolean.TRUE.equals(returnValue))
{
return node.jjtGetChild(1).jjtAccept(this, data);
} else
{
return node.jjtGetChild(2).jjtAccept(this, data);
}
} else
{
throw generateProcessingException(new IllegalArgumentException(
"condition of hook expression is not a boolean expression"), node);
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstIfStatement, java.lang.Object)
*/
public Object visit(AstIfStatement node, Object data) throws Exception
{
Boolean condition = Evaluator.toBoolean(node.jjtGetChild(0).jjtAccept(this, data));
if (condition.booleanValue())
{
return node.jjtGetChild(1).jjtAccept(this, data);
} else
{
if (node.jjtGetNumChildren() > 2)
{
return node.jjtGetChild(2).jjtAccept(this, data);
} else
{
return null;
}
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstImportDeclaration, java.lang.Object)
*/
public Object visit(AstImportDeclaration node, Object data) throws Exception
{
JxpProcessingContext context = getCurrentContext();
String packageName = toDottedName((AstName) node.jjtGetChild(0));
String className = (String) node.getData();
String importName = packageName + "." + className;
context.getImports().addImport(importName);
if (_logger.isLoggable(Level.FINEST))
{
_logger.finest("Add import " + importName);
_logger.finest(context.getImports().getPackages().toString());
}
return null;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstInstanceOfExpression, java.lang.Object)
*/
public Object visit(AstInstanceOfExpression node, Object data) throws Exception
{
Object obj = node.jjtGetChild(0).jjtAccept(this, data); //the object
if (obj == null)
{
return Boolean.FALSE; //always false
} else
{
Class c = (Class) node.jjtGetChild(1).jjtAccept(this, data);
return Boolean.valueOf(c.isInstance(obj));
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstJxpDocument, java.lang.Object)
*/
public Object visit(AstJxpDocument node, Object data) throws Exception
{
int i = 0;
int n = node.jjtGetNumChildren();
Object returnValue = null;
SimpleNode statement = null;
try
{
while (i < n)
{
statement = (SimpleNode) node.jjtGetChild(i);
returnValue = statement.jjtAccept(this, data);
if (returnValue instanceof Control)
{
return returnValue;
}
i++;
}
} catch (ProcessingException pe)
{
throw pe;
} catch (Exception e)
{
throw generateProcessingException(e, statement);
}
return null;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLabeledStatement, java.lang.Object)
*/
public Object visit(AstLabeledStatement node, Object data) throws Exception
{
throw generateProcessingException(new UnsupportedOperationException("Labeled statement: Unsupported Language Feature"),
node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLEExpression, java.lang.Object)
*/
public Object visit(AstLEExpression node, Object data) throws Exception
{
Object o1 = node.jjtGetChild(0).jjtAccept(this, data), o2 = node.jjtGetChild(1).jjtAccept(this, data);
return Evaluator.le(o1, o2);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLiteral, java.lang.Object)
*/
public Object visit(AstLiteral node, Object data) throws Exception
{
return node.getData();
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstBangUnaryExpression, java.lang.Object)
*/
public Object visit(AstLogicalComplementExpression node, Object data) throws Exception
{
Boolean b = Evaluator.toBoolean(node.jjtGetChild(0).jjtAccept(this, data));
return Boolean.valueOf(!b.booleanValue());
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLShiftAssignExpression, java.lang.Object)
*/
public Object visit(AstLShiftAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.leftShift(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLShiftExpression, java.lang.Object)
*/
public Object visit(AstLShiftExpression node, Object data) throws Exception
{
return Evaluator.leftShift(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstLTExpression, java.lang.Object)
*/
public Object visit(AstLTExpression node, Object data) throws Exception
{
Object o1 = node.jjtGetChild(0).jjtAccept(this, data), o2 = node.jjtGetChild(1).jjtAccept(this, data);
return Evaluator.lt(o1, o2);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMethodCall, java.lang.Object)
*/
public Object visit(AstMethodCall node, Object data) throws Exception
{
String methodName = (String) node.getData();
Object[] args = resolveArguments((AstArguments) node.jjtGetChild(0), getCurrentContext());
if (args.length == 0)
{
if (methodName.equals("flush"))
{
flush();
return null;
}
} else if (args[0] instanceof String && args.length == 1)
{
/*
if (methodName.equals("process"))
{
return processCall((String) args[0]);
} else
*/
if (methodName.equals("include"))
{
return includeCall((String) args[0]);
}
}
try
{
return invokeMethod(this, methodName, args);
} catch (ProcessingException e)
{
throw e;
} catch (InvocationTargetException e)
{
Throwable t = e.getTargetException();
throw generateProcessingException(t, node);
} catch (Exception e)
{
throw generateProcessingException(e, node);
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMethodDeclaration, java.lang.Object)
*/
public Object visit(AstFunctionDeclaration node, Object data) throws Exception
{
int i = 0;
SimpleNode declarator = null;
do
{
declarator = (SimpleNode) node.jjtGetChild(i++);
} while (!(declarator instanceof AstFunctionDeclarator));
//child is FunctionDeclarator now
SimpleNode block = null;
int n = node.jjtGetNumChildren();
if (i < n)
{
do
{
block = (SimpleNode) node.jjtGetChild(i++);
} while (!(block instanceof AstBlock) && i < n);
}
return getCurrentContext().getUserDefinedFunctions().put((String) declarator.getData(),
new JxpUserDefinedFunction((SimpleNode) declarator.jjtGetChild(0), (AstBlock) block));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMethodDeclarator, java.lang.Object)
*/
public Object visit(AstFunctionDeclarator node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException(
"visit(AstFunctionDeclarator,Object) is not meant to be called."), node);
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMethodInvocation, java.lang.Object)
*/
public Object visit(AstMethodInvocation node, Object data) throws Exception
{
// the prefix node
Object obj = node.jjtGetChild(0).jjtAccept(this, data);
SimpleNode methodCall = (SimpleNode) node.jjtGetChild(1);
String methodName = (String) methodCall.getData();
if (obj == null)
{
throw generateProcessingException(new NullPointerException("Cannot invoke method " + methodName + "(...) of null at "),
node);
}
Object[] args = resolveArguments((AstArguments) methodCall.jjtGetChild(0), getCurrentContext());
try
{
return invokeMethod(obj, methodName, args);
} catch (InvocationTargetException e)
{
Throwable t = e.getTargetException();
throw generateProcessingException(t, node);
} catch (Exception e)
{
throw generateProcessingException(e, node);
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMinusAssignExpression, java.lang.Object)
*/
public Object visit(AstMinusAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.minus(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMinusExpression, java.lang.Object)
*/
public Object visit(AstMinusExpression node, Object data) throws Exception
{
return Evaluator.minus(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstStarAssignExpression, java.lang.Object)
*/
public Object visit(AstMultiplyAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.multiply(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstMultiplyExpression, java.lang.Object)
*/
public Object visit(AstMultiplyExpression node, Object data) throws Exception
{
return Evaluator.multiply(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstName, java.lang.Object)
*/
public Object visit(AstName node, Object data) throws Exception
{
List l = (List) node.getData();
try
{
return resolveName(l);
} catch (Exception e)
{
throw generateProcessingException(e, node);
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstNameList, java.lang.Object)
*/
public Object visit(AstNameList node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException("visit(ASTNameList, Object) not supposed to be called"), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstNEExpression, java.lang.Object)
*/
public Object visit(AstNEExpression node, Object data) throws Exception
{
Object o1 = node.jjtGetChild(0).jjtAccept(this, data), o2 = node.jjtGetChild(1).jjtAccept(this, data);
return Evaluator.ne(o1, o2);
}
/**
* (non-Javadoc)
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstObjectAllocationExpression, java.lang.Object)
*/
public Object visit(AstObjectAllocationExpression node, Object data) throws Exception
{
String className = toDottedName((AstName) node.jjtGetChild(0));
Class type = getCurrentContext().resolveClass(className);
if (type == null)
{
throw generateProcessingException(new ClassNotFoundException("No definition found for " + className), node);
}
Object[] args = resolveArguments((AstArguments) node.jjtGetChild(1), getCurrentContext());
try
{
return instantiate(type, args);
} catch (InvocationTargetException e)
{
Throwable t = e.getTargetException();
throw generateProcessingException(t, node);
} catch (Exception e)
{
throw generateProcessingException(e, node);
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPlusAssignExpression, java.lang.Object)
*/
public Object visit(AstPlusAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.plus(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPlusExpression, java.lang.Object)
*/
public Object visit(AstPlusExpression node, Object data) throws Exception
{
Object o1 = node.jjtGetChild(0).jjtAccept(this, data), o2 = node.jjtGetChild(1).jjtAccept(this, data);
return Evaluator.plus(o1, o2);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPostfixDecrementExpression, java.lang.Object)
*/
public Object visit(AstPostDecrementExpression node, Object data) throws Exception
{
Object returnValue = node.jjtGetChild(0).jjtAccept(this, data);
Object newValue = Evaluator.minus(returnValue, ONE);
if (resolveAssignmentTarget((SimpleNode) node.jjtGetChild(0), false) != null)
{
assign((SimpleNode) node.jjtGetChild(0), newValue);
}
return returnValue;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPostfixIncrementExpression, java.lang.Object)
*/
public Object visit(AstPostIncrementExpression node, Object data) throws Exception
{
Object returnValue = node.jjtGetChild(0).jjtAccept(this, data);
Object newValue = Evaluator.plus(returnValue, ONE);
if (resolveAssignmentTarget((SimpleNode) node.jjtGetChild(0), false) != null)
{
assign((SimpleNode) node.jjtGetChild(0), newValue);
}
return returnValue;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPreDecrementExpression, java.lang.Object)
*/
public Object visit(AstPreDecrementExpression node, Object data) throws Exception
{
Object returnValue = node.jjtGetChild(0).jjtAccept(this, data);
Object newValue = Evaluator.minus(returnValue, ONE);
//TODO: improve performance
if (resolveAssignmentTarget((SimpleNode) node.jjtGetChild(0), false) != null)
{
assign((SimpleNode) node.jjtGetChild(0), newValue);
}
return newValue;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPreIncrementExpression, java.lang.Object)
*/
public Object visit(AstPreIncrementExpression node, Object data) throws Exception
{
Object returnValue = node.jjtGetChild(0).jjtAccept(this, data);
Object newValue = Evaluator.plus(returnValue, ONE);
//TODO: improve performance
if (resolveAssignmentTarget((SimpleNode) node.jjtGetChild(0), false) != null)
{
assign((SimpleNode) node.jjtGetChild(0), newValue);
}
return newValue;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPrimaryExpression, java.lang.Object)
*/
public Object visit(AstPrimaryExpression node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException(
"visit(AstPrimaryExpression, Object) not supposed to be called."), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPrimarySuffix, java.lang.Object)
*/
public Object visit(AstPrimarySuffix node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException("visit(AstPrimarySuffix, Object) not supposed to be called."),
node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPrimitiveType, java.lang.Object)
*/
public Object visit(AstPrimitiveType node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException("visit(AstPrimitiveType, Object) not supposed to be called."),
node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstPrintStatement, java.lang.Object)
*/
public Object visit(AstPrintStatement node, Object data) throws Exception
{
print(node.jjtGetChild(0).jjtAccept(this, data));
return null;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRemainderExpression, java.lang.Object)
*/
public Object visit(AstRemainderExpression node, Object data) throws Exception
{
return Evaluator.remainder(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRemAssignExpression, java.lang.Object)
*/
public Object visit(AstRemAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.remainder(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstReturnStatement, java.lang.Object)
*/
public Object visit(AstReturnStatement node, Object data) throws Exception
{
if (node.jjtGetNumChildren() > 0)
{
return new Control(node.jjtGetChild(0).jjtAccept(this, data));
} else
{
return Control.RETURN;
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRSignedShiftAssignExpression, java.lang.Object)
*/
public Object visit(AstRSignedShiftAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.rightSignedShift(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRSignedShiftExpression, java.lang.Object)
*/
public Object visit(AstRSignedShiftExpression node, Object data) throws Exception
{
return Evaluator.rightUnsignedShift(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRUnsignedShiftAssignExpression, java.lang.Object)
*/
public Object visit(AstRUnsignedShiftAssignExpression node, Object data) throws Exception
{
Object origValue = node.jjtGetChild(0).jjtAccept(this, data), value = node.jjtGetChild(1).jjtAccept(this, data);
return assign((SimpleNode) node.jjtGetChild(0), Evaluator.rightUnsignedShift(origValue, value));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstRUnsignedShiftExpression, java.lang.Object)
*/
public Object visit(AstRUnsignedShiftExpression node, Object data) throws Exception
{
return Evaluator.rightUnsignedShift(node.jjtGetChild(0).jjtAccept(this, data), node.jjtGetChild(1).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstStatementExpressionList, java.lang.Object)
*/
public Object visit(AstStatementExpressionList node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException(
"visit(AstStatementExpressionList, Object) not supposed to be called."), node);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstSwitchStatement, java.lang.Object)
*/
public Object visit(AstSwitchStatement node, Object data) throws Exception
{
Object switchValue = node.jjtGetChild(0).jjtAccept(this, data); //resolve the value first
if (switchValue == null)
{
throw generateProcessingException(new IllegalArgumentException("Switch value cannot be null"), node);
}
int n = node.jjtGetNumChildren();
boolean matchCase = false;
for (int i = 1; i < n; i++)
{
AstCase case_ = (AstCase) node.jjtGetChild(i);
int caseChildren = case_.jjtGetNumChildren();
if (!matchCase) //haven't match before
{//try to match the case
if (caseChildren == 1)
{//must be the default: calse
matchCase = true;
} else
{
Object caseValue = case_.jjtGetChild(0).jjtAccept(this, null);
if (caseValue == null)
{
throw generateProcessingException(new IllegalArgumentException("Switch case value cannot be null"), case_);
}
if (switchValue.equals(caseValue))
{
matchCase = true;
}
}
}
if (matchCase)
{
Object obj = case_.jjtGetChild(caseChildren - 1).jjtAccept(this, null);
if (obj == Control.BREAK)
{
return null;
} else if (obj instanceof Control)
{//either return or exit
return obj;
} //else just continue to fall through
}
}
return null;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstSynchronizedStatement, java.lang.Object)
*/
public Object visit(AstSynchronizedStatement node, Object data) throws Exception
{
Object obj = node.jjtGetChild(0).jjtAccept(this, data);
if (obj == null)
{
throw generateProcessingException(new IllegalArgumentException("Cannot synchronize on null"), node);
} else
{
synchronized (obj)
{
return node.jjtGetChild(1).jjtAccept(this, data);
}
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstThrowStatement, java.lang.Object)
*/
public Object visit(AstThrowStatement node, Object data) throws Exception
{
Object o = node.jjtGetChild(0).jjtAccept(this, data);
if (o instanceof Exception)
{
throw (Exception) o;
} else
{
throw generateProcessingException(new IllegalArgumentException("Cannot throw non-exception " + o), node);
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstTryStatement, java.lang.Object)
*/
public Object visit(AstTryStatement node, Object data) throws Exception
{
int n = node.jjtGetNumChildren();
int i = 0;
try
{
SimpleNode block = (SimpleNode) node.jjtGetChild(0);
return block.jjtAccept(this, data);
} catch (Throwable e)
{
JxpProcessingContext context = getCurrentContext();
Throwable realCause = e;
if (realCause instanceof ProcessingException && realCause.getCause() != null)
{
realCause = realCause.getCause();
}
for (i = 1; i < n; i++)
{
SimpleNode handlerBlock = (SimpleNode) node.jjtGetChild(i);
if (handlerBlock instanceof AstCatchBlock)
{
//catchblock
//SimpleNode formalParameter = (SimpleNode) handlerBlock.jjtGetChild(0);
AstType type = (AstType) handlerBlock.jjtGetChild(0);
Class c = (Class) type.jjtAccept(this, data);
if (c.isAssignableFrom(realCause.getClass()))
{
int scope = context.getNametableStack().newScope();
try
{
AstVariableDeclaratorId id = (AstVariableDeclaratorId) handlerBlock.jjtGetChild(1);
context.getNametableStack().declare((String) id.getData(), realCause);
return handlerBlock.jjtGetChild(2).jjtAccept(this, data); //execute the catch block
} catch (Exception eAgain)
{
//again
throw generateProcessingException(eAgain, (SimpleNode) handlerBlock.jjtGetChild(1));
} finally
{
context.getNametableStack().closeScope(scope);
}
}
}
} //exception has no handler
if (e instanceof ProcessingException)
{
throw (ProcessingException) e; //rethrown - should be because of block
} else
{
throw new IllegalStateException("Should be ProcessingException after try block");
}
} finally
{
if (i < n)
{ //still something un
SimpleNode block = (SimpleNode) node.jjtGetChild(n - 1);
if (block instanceof AstFinallyBlock)
{
block.jjtAccept(this, data);
}
}
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstUnaryMinusExpression, java.lang.Object)
*/
public Object visit(AstUnaryMinusExpression node, Object data) throws Exception
{
return Evaluator.negate(node.jjtGetChild(0).jjtAccept(this, data));
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstUnaryPlusExpression, java.lang.Object)
*/
public Object visit(AstUnaryPlusExpression node, Object data) throws Exception
{
return node.jjtGetChild(0).jjtAccept(this, data);
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstVariableDeclarator, java.lang.Object)
*/
public Object visit(AstVariableDeclarator node, Object data) throws Exception
{
Object[] passOn = (Object[]) data;
Object value = null;
if (node.jjtGetNumChildren() > 1)
{ //has initializer
value = node.jjtGetChild(1).jjtAccept(this, null);
} else
{
AstType type = (AstType) passOn[0];
if (type.jjtGetChild(0) instanceof AstPrimitiveType)
{
AstPrimitiveType primitive = (AstPrimitiveType) type.jjtGetChild(0);
value = PRIMITIVE_DEFAULTS.get(primitive.getData());
}
}
String variableName = (String) ((AstVariableDeclaratorId) node.jjtGetChild(0)).getData();
if (((Boolean) passOn[1]).booleanValue())
{//static variable flag, pass from visit(AstFieldDeclaration)
JxpPage page = getCurrentContext().getCurrentPage();
if (!page.hasStaticVariable(variableName))
{
page.declareStaticVariable(variableName, value);
}
return value;
} else
{
getCurrentContext().getNametableStack().declare(variableName, value);
return value;
}
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.AstWhileStatement, java.lang.Object)
*/
public Object visit(AstWhileStatement node, Object data) throws Exception
{
Node condition = node.jjtGetChild(0);
Boolean b = Evaluator.toBoolean(condition.jjtAccept(this, data));
Object returnValue = null;
while (b.booleanValue())
{
returnValue = node.jjtGetChild(1).jjtAccept(this, data);
if (returnValue instanceof Control)
{
if (returnValue == Control.CONTINUE)
{
returnValue = null; //clear up
} else if (returnValue == Control.BREAK)
{
returnValue = null; //clear up
break;
} else
{ //must be return w/wo object
break;
}
}
b = Evaluator.toBoolean(condition.jjtAccept(this, data));
}
return returnValue;
}
/**
* @see jxp.parser.JxpParserVisitor#visit(jxp.parser.SimpleNode, java.lang.Object)
*/
public Object visit(SimpleNode node, Object data) throws Exception
{
throw new IllegalStateException("Illegal state");
}
/**
* Flush the writer
* @throws IOException if there's io exception
*/
public void flush() throws IOException
{
getCurrentContext().getWriter().flush();
}
/**
* {@inheritDoc}
* @todo support array type
* TODO support array type
*/
public Object visit(AstType node, Object data) throws Exception
{
Node child = node.jjtGetChild(0);
Class c = null;
if (child instanceof AstName)
{
AstName name = (AstName) child;
String className = toDottedName(name);
c = getCurrentContext().resolveClass(className);
if (c == null)
{
throw generateProcessingException(new ClassNotFoundException("Class " + className + " not found"), node);
}
} else
{//primitive type
c = (Class) ((AstPrimitiveType)child).getData();
}
//TODO: work on the dimension
return c;
}
/**
* Get the method stats
* @return the method stats
*/
public Counter getMethodStats()
{
return _methodStats;
}
/**
* {@inheritDoc}
*/
public Object visit(AstVariableDeclaratorId node, Object data) throws Exception
{
// TODO Auto-generated method stub
throw generateProcessingException(new IllegalStateException(
"visit(AstVariableDeclaratorId,Object) should not be called directly"), node);
}
/**
* {@inheritDoc}
*/
public Object visit(AstExitStatement node, Object data) throws Exception
{
return Control.EXIT;
}
/**
* {@inheritDoc}
*/
public Object visit(AstStaticImportDeclaration node, Object data) throws Exception
{
JxpProcessingContext context = getCurrentContext();
AstName name = (AstName) node.jjtGetChild(0);
String className = toDottedName(name);
Class c = context.resolveClass(className);
if (c == null)
{
throw generateProcessingException(new IllegalArgumentException("Cannot resolve class " + className), node);
}
StaticImport si = StaticImportUtils.getStaticImport(c);
context.addStaticImport(si);
Iterator it = si.getStaticFields().entrySet().iterator();
NametableStack ntStack = context.getNametableStack();
while (it.hasNext())
{
Map.Entry entry = (Map.Entry) it.next();
ntStack.declare((String) entry.getKey(), entry.getValue());
}
return null;
}
/**
* {@inheritDoc}
*/
public Object visit(AstVariableParameters node, Object data) throws Exception
{
throw generateProcessingException(new IllegalStateException("visit(AstVariableParameters) should not be called directly"),
node);
}
/**
* {@inheritDoc}
*/
public Object visit(AstEnhancedForStatement node, Object data) throws Exception
{
JxpProcessingContext context = getCurrentContext();
String variable = (String) node.getData();
Node statements = node.jjtGetChild(2);
Object colObj = node.jjtGetChild(1).jjtAccept(this, data);
if (colObj instanceof Collection)
{//must be
Object returnValue = null;
Iterator it = ((Collection) colObj).iterator();
int newscope = context.getNametableStack().newScope();
try
{
context.getNametableStack().declare(variable, null);
while (it.hasNext())
{
assignVariable(variable, it.next());
returnValue = statements.jjtAccept(this, data);
if (returnValue == Control.CONTINUE)
{
returnValue = null;
//let it pass
} else if (returnValue == Control.BREAK)
{
returnValue = null;
break;
} else if (returnValue instanceof Control)
{ //must be return w/wo object
break;
}
}
return returnValue;
} finally
{
context.getNametableStack().closeScope(newscope);
}
} else
{
throw generateProcessingException(new IllegalArgumentException(
"Expression for enhanced for loop must be collection, get " + colObj + " instead"), node);
}
}
public void setDoMethodStats(boolean flag)
{
doMethodStats = flag;
}
public Object visit(AstNamedArgument node, Object data) throws Exception
{
return node; //process it later
}
/**
* Get current environment
* @return the environment
*/
public Map getEnvironment()
{
return getCurrentContext().getNametableStack().asMap();
}
/**
* Return the checkFunctionArgumentType
* @return the checkFunctionArgumentType.
*/
protected final boolean isCheckFunctionArgumentType()
{
return _checkFunctionArgumentType;
}
/**
* Set the checkFunctionArgumentType
* @param checkFunctionArgumentType The checkFunctionArgumentType to set.
*/
protected final void setCheckFunctionArgumentType(boolean checkFunctionArgumentType)
{
_checkFunctionArgumentType = checkFunctionArgumentType;
}
public Object visit(AstPageDirective node, Object data) throws Exception
{
Map m = (Map)node.getData();
if (m.containsKey("import")){
String imports = (String)m.get("import");
JxpProcessingContext context = getCurrentContext();
StringTokenizer st = new StringTokenizer(imports, ",");
while (st.hasMoreTokens()){
String im = st.nextToken();
context.getImports().addImport(im);
}
}
return null;
}
public Object visit(AstIncludeDirective node, Object data) throws Exception
{
return null;
}
public Object visit(AstIsEmptyExpression node, Object data) throws Exception
{
Object obj = node.jjtGetChild(0).jjtAccept(this, data);
return Boolean.valueOf(StringUtils.isNullOrEmpty(obj));
}
}