You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ad...@apache.org on 2008/12/27 03:31:06 UTC
svn commit: r729583 [2/2] - in /ofbiz/trunk/framework/base: lib/
src/org/ofbiz/base/util/collections/ src/org/ofbiz/base/util/string/
Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java?rev=729583&r1=729582&r2=729583&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java Fri Dec 26 18:31:05 2008
@@ -18,20 +18,29 @@
*******************************************************************************/
package org.ofbiz.base.util.string;
+import java.util.List;
+import java.util.Locale;
import java.util.Map;
import javax.el.*;
+import javolution.util.FastList;
import javolution.util.FastMap;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilGenerics;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.collections.LocalizedMap;
+
/** Implements the Unified Expression Language (JSR-245). */
public class UelUtil {
-
- protected static final ExpressionFactory exprFactory = new de.odysseus.el.ExpressionFactoryImpl();
- protected static final ELResolver defaultResolver = new CompositeELResolver() {
+ protected static final String module = UelUtil.class.getName();
+ public static final String localizedMapLocaleKey = LocalizedMap.class.getName() + ".locale";
+ protected static final ExpressionFactory exprFactory = JuelConnector.newExpressionFactory();
+ protected static final ELResolver defaultResolver = new ExtendedCompositeResolver() {
{
+ add(new ExtendedMapResolver(false));
+ add(new ExtendedListResolver(false));
add(new ArrayELResolver(false));
- add(new ListELResolver(false));
- add(new MapELResolver(false));
add(new ResourceBundleELResolver());
add(new BeanELResolver(false));
}
@@ -44,11 +53,55 @@
* @throws Various <code>javax.el.*</code> exceptions
*/
public static Object evaluate(Map<String, ? extends Object> context, String expression) {
+ return evaluate(context, expression, Object.class);
+ }
+
+ /** Evaluates a Unified Expression Language expression and returns the result.
+ * @param context Evaluation context (variables)
+ * @param expression UEL expression
+ * @param expectedType The expected object Class to return
+ * @return Result object
+ * @throws Various <code>javax.el.*</code> exceptions
+ */
+ @SuppressWarnings("unchecked")
+ public static Object evaluate(Map<String, ? extends Object> context, String expression, Class expectedType) {
ELContext elContext = new BasicContext(context);
- ValueExpression ve = exprFactory.createValueExpression(elContext, expression, Object.class);
+ ValueExpression ve = exprFactory.createValueExpression(elContext, expression, expectedType);
return ve.getValue(elContext);
}
+ /** Evaluates a Unified Expression Language expression and sets the resulting object
+ * to the specified value.
+ * @param context Evaluation context (variables)
+ * @param expression UEL expression
+ * @param expectedType The expected object Class to set
+ * @throws Various <code>javax.el.*</code> exceptions
+ */
+ @SuppressWarnings("unchecked")
+ public static void setValue(Map<String, Object> context, String expression, Class expectedType, Object value) {
+ if (Debug.verboseOn()) {
+ Debug.logVerbose("UelUtil.setValue invoked, expression = " + expression + ", value = " + value, module);
+ }
+ ELContext elContext = new BasicContext(context);
+ ValueExpression ve = exprFactory.createValueExpression(elContext, expression, expectedType);
+ ve.setValue(elContext, value);
+ }
+
+ /** Evaluates a Unified Expression Language expression and sets the resulting object
+ * to null.
+ * @param context Evaluation context (variables)
+ * @param expression UEL expression
+ * @throws Various <code>javax.el.*</code> exceptions
+ */
+ public static void removeValue(Map<String, Object> context, String expression) {
+ if (Debug.verboseOn()) {
+ Debug.logVerbose("UelUtil.removeValue invoked, expression = " + expression , module);
+ }
+ ELContext elContext = new BasicContext(context);
+ ValueExpression ve = exprFactory.createValueExpression(elContext, expression, Object.class);
+ ve.setValue(elContext, null);
+ }
+
protected static class BasicContext extends ELContext {
protected final VariableMapper variableMapper;
public BasicContext(Map<String, ? extends Object> context) {
@@ -63,68 +116,221 @@
public VariableMapper getVariableMapper() {
return this.variableMapper;
}
- protected class BasicVariableMapper extends VariableMapper {
- protected final ELContext elContext;
- protected final Map<String, Object> variables = FastMap.newInstance();
- protected BasicVariableMapper(Map<String, ? extends Object> context, ELContext parentContext) {
- this.variables.putAll(context);
- this.elContext = parentContext;
- }
- public ValueExpression resolveVariable(String variable) {
- Object obj = this.variables.get(variable);
- if (obj != null) {
- return new BasicValueExpression(obj);
- }
- return null;
- }
- public ValueExpression setVariable(String variable, ValueExpression expression) {
- return new BasicValueExpression(this.variables.put(variable, expression.getValue(this.elContext)));
+ }
+
+ protected static class BasicVariableMapper extends VariableMapper {
+ protected final ELContext elContext;
+ protected final Map<String, Object> variables;
+ protected BasicVariableMapper(Map<String, ? extends Object> context, ELContext parentContext) {
+ this.variables = UtilGenerics.cast(context);
+ this.elContext = parentContext;
+ }
+ public ValueExpression resolveVariable(String variable) {
+ Object obj = this.variables.get(variable);
+ if (obj != null) {
+ return new BasicValueExpression(obj);
}
+ return null;
+ }
+ public ValueExpression setVariable(String variable, ValueExpression expression) {
+ return new BasicValueExpression(this.variables.put(variable, expression.getValue(this.elContext)));
+ }
+ }
+
+ @SuppressWarnings("serial")
+ protected static class BasicValueExpression extends ValueExpression {
+ protected Object object;
+ public BasicValueExpression(Object object) {
+ super();
+ this.object = object;
+ }
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ try {
+ BasicValueExpression other = (BasicValueExpression) obj;
+ return this.object.equals(other.object);
+ } catch (Exception e) {}
+ return false;
+ }
+ public int hashCode() {
+ return this.object == null ? 0 : this.object.hashCode();
+ }
+ public Object getValue(ELContext context) {
+ return this.object;
+ }
+ public String getExpressionString() {
+ return null;
}
- @SuppressWarnings("serial")
- protected class BasicValueExpression extends ValueExpression {
- protected Object object;
- public BasicValueExpression(Object object) {
- super();
- this.object = object;
- }
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
+ public boolean isLiteralText() {
+ return false;
+ }
+ public Class<?> getType(ELContext context) {
+ return this.object == null ? null : this.object.getClass();
+ }
+ public boolean isReadOnly(ELContext context) {
+ return false;
+ }
+ public void setValue(ELContext context, Object value) {
+ this.object = value;
+ }
+ public String toString() {
+ return "ValueExpression(" + this.object + ")";
+ }
+ public Class<?> getExpectedType() {
+ return this.object == null ? null : this.object.getClass();
+ }
+ }
+
+ /** Custom <code>CompositeELResolver</code> used to handle variable
+ * auto-vivify.
+ */
+ protected static class ExtendedCompositeResolver extends CompositeELResolver {
+ public void setValue(ELContext context, Object base, Object property, Object val) {
+ super.setValue(context, base, property, val);
+ if (!context.isPropertyResolved() && base == null) {
+ if (Debug.verboseOn()) {
+ Debug.logVerbose("ExtendedCompositeResolver.setValue: base = " + base + ", property = " + property + ", value = " + val, module);
}
- try {
- BasicValueExpression other = (BasicValueExpression) obj;
- return this.object.equals(other.object);
- } catch (Exception e) {}
- return false;
- }
- public int hashCode() {
- return this.object == null ? 0 : this.object.hashCode();
+ ValueExpression ve = new BasicValueExpression(val);
+ VariableMapper vm = context.getVariableMapper();
+ vm.setVariable(property.toString(), ve);
+ context.setPropertyResolved(true);
+ return;
}
- public Object getValue(ELContext context) {
- return this.object;
- }
- public String getExpressionString() {
- return null;
- }
- public boolean isLiteralText() {
- return false;
- }
- public Class<?> getType(ELContext context) {
- return this.object == null ? null : this.object.getClass();
- }
- public boolean isReadOnly(ELContext context) {
- return false;
- }
- public void setValue(ELContext context, Object value) {
- this.object = value;
- }
- public String toString() {
- return "ValueExpression(" + this.object + ")";
+ }
+ }
+
+ /** Custom <code>ListELResolver</code> used to handle OFBiz
+ * <code>List</code> syntax.
+ */
+ protected static class ExtendedListResolver extends ListELResolver {
+ protected boolean isReadOnly;
+ public ExtendedListResolver(boolean isReadOnly) {
+ super(isReadOnly);
+ this.isReadOnly = isReadOnly;
+ }
+ @SuppressWarnings("unchecked")
+ public void setValue(ELContext context, Object base, Object property, Object val) {
+ if (context == null) {
+ throw new NullPointerException();
+ }
+ if (base != null && base instanceof List) {
+ if (isReadOnly) {
+ throw new PropertyNotWritableException();
+ }
+ String str = property.toString();
+ if ("add".equals(str)) {
+ if (Debug.verboseOn()) {
+ Debug.logVerbose("ExtendedListResolver.setValue adding List element: base = " + base + ", property = " + property + ", value = " + val, module);
+ }
+ context.setPropertyResolved(true);
+ List list = (List) base;
+ list.add(val);
+ } else if (str.startsWith("insert@")){
+ if (Debug.verboseOn()) {
+ Debug.logVerbose("ExtendedListResolver.setValue inserting List element: base = " + base + ", property = " + property + ", value = " + val, module);
+ }
+ context.setPropertyResolved(true);
+ String indexStr = str.replace("insert@", "");
+ int index = Integer.parseInt(indexStr);
+ List list = (List) base;
+ try {
+ list.add(index, val);
+ } catch (UnsupportedOperationException ex) {
+ throw new PropertyNotWritableException();
+ } catch (IndexOutOfBoundsException ex) {
+ throw new PropertyNotFoundException();
+ }
+ } else {
+ super.setValue(context, base, property, val);
+ }
}
- public Class<?> getExpectedType() {
- return this.object == null ? null : this.object.getClass();
+ }
+ }
+
+ /** Custom <code>MapELResolver</code> class used to accomodate
+ * <code>LocalizedMap</code> instances.
+ */
+ protected static class ExtendedMapResolver extends MapELResolver {
+ public ExtendedMapResolver(boolean isReadOnly) {
+ super(isReadOnly);
+ }
+ @SuppressWarnings("unchecked")
+ public Object getValue(ELContext context, Object base, Object property) {
+ if (context == null) {
+ throw new NullPointerException();
+ }
+ if (base != null && base instanceof LocalizedMap) {
+ context.setPropertyResolved(true);
+ LocalizedMap map = (LocalizedMap) base;
+ Locale locale = null;
+ try {
+ VariableMapper vm = context.getVariableMapper();
+ ValueExpression ve = vm.resolveVariable(localizedMapLocaleKey);
+ if (ve != null) {
+ locale = (Locale) ve.getValue(context);
+ }
+ if (locale == null) {
+ ve = vm.resolveVariable("locale");
+ if (ve != null) {
+ locale = (Locale) ve.getValue(context);
+ }
+ }
+ } catch (Exception e) {
+ Debug.logWarning("Exception thrown while getting LocalizedMap element, locale = " + locale + ", exception " + e, module);
+ }
+ if (locale == null) {
+ if (Debug.verboseOn()) {
+ Debug.logVerbose("ExtendedMapResolver.getValue: unable to find Locale for LocalizedMap element, using default locale", module);
+ }
+ locale = Locale.getDefault();
+ }
+ return map.get(property.toString(), locale);
}
+ return super.getValue(context, base, property);
+ }
+ }
+
+ /** Evaluates a property <code>Object</code> and returns a new
+ * <code>List</code> or <code>Map</code>. If <code>property</code>
+ * evaluates to an integer value, a new <code>List</code> instance
+ * is returned, otherwise a new <code>Map</code> instance is
+ * returned.
+ * @param property Property <code>Object</code> to be evaluated
+ * @return New <code>List</code> or <code>Map</code>
+ */
+ public static Object autoVivifyListOrMap(Object property) {
+ String str = property.toString();
+ boolean isList = ("add".equals(str) || str.startsWith("insert@"));
+ if (!isList) {
+ Integer index = UtilMisc.toIntegerObject(property);
+ isList = (index != null);
+ }
+ if (isList) {
+ return FastList.newInstance();
+ } else {
+ return FastMap.newInstance();
+ }
+ }
+
+ /** Prepares an expression for evaluation by UEL. The OFBiz syntax is
+ * converted to UEL-compatible syntax and the resulting expression is
+ * returned.
+ * @param expression Expression to be converted
+ * @return Converted expression
+ */
+ public static String prepareExpression(String expression) {
+ int openBrace = expression.indexOf("[+");
+ int closeBrace = (openBrace == -1 ? -1 : expression.indexOf(']', openBrace));
+ if (closeBrace != -1) {
+ String base = expression.substring(0, openBrace);
+ String property = expression.substring(openBrace+2, closeBrace).trim();
+ String end = expression.substring(closeBrace + 1);
+ expression = base + "['insert@" + property + "']" + end;
}
+ expression = expression.replace("[]", "['add']");
+ return expression;
}
}