001: /* MVELFactory.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Sun Sep 2 21:04:06 2007, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zkmax.xel.mvel;
020:
021: import java.util.Collection;
022: import java.util.List;
023: import java.util.Iterator;
024:
025: import org.mvel.MVEL;
026: import org.mvel.ParserContext;
027: import org.mvel.ExpressionCompiler;
028: import org.mvel.util.ParseTools;
029:
030: import org.zkoss.lang.Classes;
031: import org.zkoss.xel.ExpressionFactory;
032: import org.zkoss.xel.Expression;
033: import org.zkoss.xel.XelContext;
034: import org.zkoss.xel.FunctionMapper;
035: import org.zkoss.xel.XelException;
036:
037: import org.zkoss.zkmax.xel.util.ExpressionFragment;
038:
039: /**
040: * An implementation based on MVEL.
041: *
042: * <p>Note: MVEL is not completely compatible with JSP EL.
043: *
044: * <p>See also <a href="http://mvel.codehaus.org/">MVEL website</a>.
045: *
046: * @author tomyeh
047: * @since 3.0.0
048: */
049: public class MVELFactory implements ExpressionFactory {
050: //ExpressionFactory//
051: public boolean isSupported(int feature) {
052: return feature == FEATURE_CLASS;
053: }
054:
055: public Expression parseExpression(XelContext ctx,
056: String expression, Class expectedType) throws XelException {
057: final ParserContext pctx = getParserContext(ctx);
058: final List frags = ExpressionFragment.parse(expression);
059: final Object[] fs = new Object[frags.size()];
060: int j = 0;
061: for (Iterator it = frags.iterator(); it.hasNext(); ++j) {
062: final Object o = it.next();
063: if (o instanceof ExpressionFragment) {
064: fs[j] = compile(((ExpressionFragment) o)
065: .getExpression(), pctx);
066: } else {
067: fs[j] = o;
068: }
069: }
070: return new MVELXelExpression(fs, expectedType);
071: }
072:
073: public Object evaluate(XelContext ctx, String expression,
074: Class expectedType) throws XelException {
075: final XelMVELResolver resolver = new XelMVELResolver(ctx
076: .getVariableResolver());
077:
078: final ParserContext pctx = getParserContext(ctx);
079:
080: final List frags = ExpressionFragment.parse(expression);
081: if (frags.size() == 1) { //optimize this most common case
082: final Object o = frags.get(0);
083: return Classes.coerce(expectedType, o instanceof String ? o
084: : eval(((ExpressionFragment) o).getExpression(),
085: resolver, pctx));
086: }
087:
088: final StringBuffer sb = new StringBuffer(256);
089: for (Iterator it = frags.iterator(); it.hasNext();) {
090: final Object o = it.next();
091: if (o instanceof String) {
092: sb.append(o);
093: } else {
094: Object val = eval(((ExpressionFragment) o)
095: .getExpression(), resolver, pctx);
096: if (val != null)
097: sb.append(val);
098: }
099: }
100: return Classes.coerce(expectedType, sb.toString());
101: }
102:
103: private Object eval(String expr, XelMVELResolver resolver,
104: ParserContext pctx) {
105: return pctx == null ? MVEL.eval(expr, resolver) : MVEL
106: .executeExpression(compile(expr, pctx), resolver);
107: }
108:
109: private Object compile(String expr, ParserContext pctx) {
110: return pctx == null ? MVEL.compileExpression(expr) : ParseTools
111: .optimizeTree(new ExpressionCompiler(expr)
112: .compile(pctx));
113: }
114:
115: private ParserContext getParserContext(XelContext ctx) {
116: if (ctx != null) {
117: final FunctionMapper mapper = ctx.getFunctionMapper();
118: if (mapper != null) {
119: final Collection c = mapper.getClassNames();
120: if (c != null && !c.isEmpty()) {
121: final ParserContext pctx = new ParserContext();
122: for (Iterator it = c.iterator(); it.hasNext();) {
123: final String nm = (String) it.next();
124: pctx.addImport(nm, mapper.resolveClass(nm));
125: }
126: return pctx;
127: }
128: }
129: }
130: return null;
131: }
132: }
|