/* Expressions.java Purpose: Description: History: Thu Aug 30 11:09:33 2007, Created by tomyeh Copyright (C) 2007 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under LGPL Version 2.1 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.xel; import java.util.Collection; import java.util.Collections; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zkoss.lang.Classes; /** * Utilities to use XEL. * * @author tomyeh * @since 3.0.0 */ public class Expressions { private static final Logger log = LoggerFactory.getLogger(Expressions.class); /** An empty function mapper, i.e., it has no function defined at all. * It is serializable. */ public static final FunctionMapper EMPTY_MAPPER = new EmptyMapper(); /** An empty variable resolver, i.e., it has no variable defined at all. * It is serializable. */ public static final VariableResolver EMPTY_RESOLVER = new EmptyResolver(); /** An dummy expression that does nothing. * It is usually used as a flag to denote exceptional cases. * It it serializable. */ public static final Expression DUMMY_EXPRESSION = new DummyExpr(); /** The implementation of {@link ExpressionFactory}. */ private static Class<? extends ExpressionFactory> _expfcls; /** Instantiates an instance of {@link ExpressionFactory}. * * <p>The default class is {@link org.zkoss.xel.el.ELFactory}, * which supports EL 2.0. * If you run under JVM 1.5 or later and deploy * <a href="http://code.google.com/p/zel/">zel.jar</a> in your class * path, the default class is then {@link org.zkoss.xel.zel.ELFactory} * which supports EL 2.2. * To override it, you can specify the class by calling * {@link #setExpressionFactoryClass}, or use * {@link #newExpressionFactory(Class)} instead. * * <p>For the ZK user, you can override it with zk.xml * or org.zkoss.zk.ui.util.Configuration. * * @exception XelException if the specified class failed to load, * or instantiate. */ public static final ExpressionFactory newExpressionFactory() throws XelException { return newExpressionFactory(_expfcls); } /** Instantiates an instance of {@link ExpressionFactory}. * * <p>The default class is {@link org.zkoss.xel.el.ELFactory}, * which supports EL 2.0. * If you run under JVM 1.5 or later and deploy * <a href="http://code.google.com/p/zel/">zel.jar</a> in your class * path, the default class is then {@link org.zkoss.xel.zel.ELFactory} * which supports EL 2.2. * To override it, you can specify the class by calling * {@link #setExpressionFactoryClass}, or specifying the class you prefer * in the expfcls argument. * * <p>For the ZK user, you can override it with zk.xml * or org.zkoss.zk.ui.util.Configuration. * * @param expfcls the class that implements {@link ExpressionFactory}, * or null to use the default. * @exception XelException if the specified class failed to load, * or instantiate. */ public static final ExpressionFactory newExpressionFactory(Class<? extends ExpressionFactory> expfcls) { if (expfcls == null) expfcls = _expfcls; if (expfcls != null) { try { return expfcls.newInstance(); } catch (Throwable ex) { throw XelException.Aide.wrap(ex, "Unable to instantiate "+expfcls); } } return newDefautFactory(); } private static final ExpressionFactory newDefautFactory() { return _provider.newFactory(); } private static final FactoryProvider _provider; static { boolean useZel = true; try { Classes.forNameByThread("org.zkoss.zel.impl.ExpressionFactoryImpl"); } catch (Throwable e) { useZel = false; } if (useZel) { _provider = new FactoryProvider() { public ExpressionFactory newFactory() { return new org.zkoss.xel.zel.ELFactory(); } }; } else { _provider = new FactoryProvider() { public ExpressionFactory newFactory() { return new org.zkoss.xel.el.ELFactory(); } }; } } private interface FactoryProvider { public ExpressionFactory newFactory(); } /** Evaluates an expression. * * @param ctx the context information to evaluate the expression * It can be null, in which case no functions are supported for this * invocation. * @param expression the expression to be evaluated. * Note: the expression is enclosed * with ${ and }, regardless of what implementation is used. * @param expectedType the expected type of the result of the evaluation */ public static final Object evaluate(XelContext ctx, String expression, Class<?> expectedType) throws XelException { return newExpressionFactory().evaluate(ctx, expression, expectedType); } /** Sets the implementation of the expression factory that shall * be used by the whole system, or null to use the system default. * * <p>Default: null - it means {@link org.zkoss.xel.el.ELFactory}, * which supports EL 2.0. * If you run under JVM 1.5 or later and deploy * <a href="http://code.google.com/p/zel/">zel.jar</a> in your class * path, the default class is then {@link org.zkoss.xel.zel.ELFactory} * which supports EL 2.2. * * <p>Note: you can only specify an implementation that is compatible * with JSP EL here, since all built-in pages depend on it. * * @param expfcls the implementation class, or null to use the default. * Note: expfcls must implement {@link ExpressionFactory}. * If null, the system default is used. */ public static final void setExpressionFactoryClass(Class<? extends ExpressionFactory> expfcls) { if (expfcls != null && !ExpressionFactory.class.isAssignableFrom(expfcls)) throw new IllegalArgumentException(expfcls+" must implement "+ExpressionFactory.class); _expfcls = expfcls; } /** Returns the implementation of the expression factory that * is used by the whole system, or null to use the system default. * * @see #setExpressionFactoryClass */ public static final Class<? extends ExpressionFactory> getExpressionFactoryClass() { return _expfcls; } private static class EmptyMapper implements FunctionMapper, java.io.Serializable { //-- FunctionMapper --// public Function resolveFunction(String prefix, String name) { return null; } public Collection<String> getClassNames() { return Collections.emptyList(); } public Class<?> resolveClass(String name) { return null; } } private static class EmptyResolver implements VariableResolver, java.io.Serializable { public Object resolveVariable(String name) { return null; } } private static class DummyExpr implements Expression, java.io.Serializable { public Object evaluate(XelContext ctx) throws XelException { return null; } }; }