
org.jdesktop.el.impl.lang.ExpressionBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swixml Show documentation
Show all versions of swixml Show documentation
GUI generating engine for Java applications
The newest version!
/*
* Copyright (C) 2007 Sun Microsystems, Inc. All rights reserved. Use is
* subject to license terms.
*/
package org.jdesktop.el.impl.lang;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jdesktop.el.ELContext;
import org.jdesktop.el.ELException;
import org.jdesktop.el.FunctionMapper;
import org.jdesktop.el.MethodExpression;
import org.jdesktop.el.ValueExpression;
import org.jdesktop.el.VariableMapper;
import org.jdesktop.el.impl.MethodExpressionImpl;
import org.jdesktop.el.impl.MethodExpressionLiteral;
import org.jdesktop.el.impl.ValueExpressionImpl;
import org.jdesktop.el.impl.parser.AstCompositeExpression;
import org.jdesktop.el.impl.parser.AstDeferredExpression;
import org.jdesktop.el.impl.parser.AstDynamicExpression;
import org.jdesktop.el.impl.parser.AstFunction;
import org.jdesktop.el.impl.parser.AstIdentifier;
import org.jdesktop.el.impl.parser.AstLiteralExpression;
import org.jdesktop.el.impl.parser.AstValue;
import org.jdesktop.el.impl.parser.ELParser;
import org.jdesktop.el.impl.parser.Node;
import org.jdesktop.el.impl.parser.NodeVisitor;
import org.jdesktop.el.impl.parser.ParseException;
import org.jdesktop.el.impl.util.MessageFactory;
/**
* @author Jacob Hookom [[email protected]]
* @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $
*/
public final class ExpressionBuilder implements NodeVisitor {
private static final int SIZE = 5000;
private static final Map cache = new ConcurrentHashMap(SIZE);
private static final Map cache2 = new ConcurrentHashMap(SIZE);
private FunctionMapper fnMapper;
private VariableMapper varMapper;
private String expression;
/**
*
*/
public ExpressionBuilder(String expression, ELContext ctx)
throws ELException {
this.expression = expression;
FunctionMapper ctxFn = ctx.getFunctionMapper();
VariableMapper ctxVar = ctx.getVariableMapper();
if (ctxFn != null) {
this.fnMapper = new FunctionMapperFactory(ctxFn);
}
if (ctxVar != null) {
this.varMapper = new VariableMapperFactory(ctxVar);
}
}
public final static Node createNode(String expr) throws ELException {
Node n = createNodeInternal(expr);
return n;
}
private final static Node createNodeInternal(String expr)
throws ELException {
if (expr == null) {
throw new ELException(MessageFactory.get("error.null"));
}
Node n = (Node) cache.get(expr);
if (n == null && (n = (Node) cache2.get(expr)) == null) {
try {
n = (new ELParser(new StringReader(expr)))
.CompositeExpression();
// validate composite expression
if (n instanceof AstCompositeExpression) {
int numChildren = n.jjtGetNumChildren();
if (numChildren == 1) {
n = n.jjtGetChild(0);
} else {
Class type = null;
Node child = null;
for (int i = 0; i < numChildren; i++) {
child = n.jjtGetChild(i);
if (child instanceof AstLiteralExpression)
continue;
if (type == null)
type = child.getClass();
else {
if (!type.equals(child.getClass())) {
throw new ELException(MessageFactory.get(
"error.mixed", expr));
}
}
}
}
}
if (n instanceof AstDeferredExpression
|| n instanceof AstDynamicExpression) {
n = n.jjtGetChild(0);
}
if (cache.size() > SIZE) {
cache2.clear();
cache2.putAll(cache);
cache.clear();
}
cache.put(expr, n);
} catch (ParseException pe) {
throw new ELException("Error Parsing: " + expr, pe);
}
}
return n;
}
private void prepare(Node node) throws ELException {
node.accept(this);
if (this.fnMapper instanceof FunctionMapperFactory) {
this.fnMapper = ((FunctionMapperFactory) this.fnMapper).create();
}
if (this.varMapper instanceof VariableMapperFactory) {
this.varMapper = ((VariableMapperFactory) this.varMapper).create();
}
}
private Node build() throws ELException {
Node n = createNodeInternal(this.expression);
this.prepare(n);
if (n instanceof AstDeferredExpression
|| n instanceof AstDynamicExpression) {
n = n.jjtGetChild(0);
}
return n;
}
/*
* (non-Javadoc)
*
* @see com.sun.el.parser.NodeVisitor#visit(com.sun.el.parser.Node)
*/
public void visit(Node node) throws ELException {
if (node instanceof AstFunction) {
AstFunction funcNode = (AstFunction) node;
if (this.fnMapper == null) {
throw new ELException(MessageFactory.get("error.fnMapper.null"));
}
Method m = fnMapper.resolveFunction(funcNode.getPrefix(), funcNode
.getLocalName());
if (m == null) {
throw new ELException(MessageFactory.get(
"error.fnMapper.method", funcNode.getOutputName()));
}
int pcnt = m.getParameterTypes().length;
if (node.jjtGetNumChildren() != pcnt) {
throw new ELException(MessageFactory.get(
"error.fnMapper.paramcount", funcNode.getOutputName(),
"" + pcnt, "" + node.jjtGetNumChildren()));
}
} else if (node instanceof AstIdentifier && this.varMapper != null) {
String variable = ((AstIdentifier) node).getImage();
// simply capture it
this.varMapper.resolveVariable(variable);
}
}
public ValueExpression createValueExpression(Class expectedType)
throws ELException {
Node n = this.build();
return new ValueExpressionImpl(this.expression, n, this.fnMapper,
this.varMapper, expectedType);
}
public MethodExpression createMethodExpression(Class expectedReturnType,
Class[] expectedParamTypes) throws ELException {
Node n = this.build();
if (n instanceof AstValue || n instanceof AstIdentifier) {
return new MethodExpressionImpl(expression, n,
this.fnMapper, this.varMapper, expectedReturnType,
expectedParamTypes);
} else if (n instanceof AstLiteralExpression) {
return new MethodExpressionLiteral(expression, expectedReturnType,
expectedParamTypes);
} else {
throw new ELException("Not a Valid Method Expression: "
+ expression);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy