Author: henrib Date: Sat Aug 1 14:51:49 2015 New Revision: 1693711 URL: http://svn.apache.org/r1693711 Log: JEXL: JEXL-171: added JexlUberspect.ResolverStrategy
Added: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/StrategyTest.java (with props) Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/IntegerRange.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/LongRange.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/SandboxUberspect.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlUberspect.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/introspection/DiscoveryTest.java Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java Sat Aug 1 14:51:49 2015 @@ -67,6 +67,10 @@ public class JexlBuilder { */ protected JexlUberspect uberspect = null; /** + * The resolver strategy. + */ + protected JexlUberspect.ResolverStrategy resolver = null; + /** * The sandbox. */ protected JexlSandbox sandbox = null; @@ -128,6 +132,22 @@ public class JexlBuilder { } /** + * Sets the JexlUberspect resolver strategy the engine will use. + * <p>This is ignored if the uberspect has been set. + * @param rs the strategy + * @return this builder + */ + public JexlBuilder strategy(JexlUberspect.ResolverStrategy rs) { + this.resolver = rs; + return this; + } + + /** @return the resolver strategy */ + public JexlUberspect.ResolverStrategy strategy() { + return this.resolver; + } + + /** * Sets the JexlArithmetic instance the engine will use. * @param a the arithmetic * @return this builder Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java Sat Aug 1 14:51:49 2015 @@ -156,6 +156,13 @@ public final class Debugger extends Pars public boolean debug(JexlNode node) { return debug(node, true); } + + /** + * Seeks the location of an error cause (a node) in an expression. + * @param node the node to debug + * @param r whether we should actively find the root node of the debugged node + * @return true if the cause was located, false otherwise + */ public boolean debug(JexlNode node, boolean r) { start = 0; end = 0; @@ -167,9 +174,9 @@ public final class Debugger extends Pars // make arg cause become the root cause JexlNode root = node; if (r) { - while (root.jjtGetParent() != null) { - root = root.jjtGetParent(); - } + while (root.jjtGetParent() != null) { + root = root.jjtGetParent(); + } } root.jjtAccept(this, null); } Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java Sat Aug 1 14:51:49 2015 @@ -68,7 +68,7 @@ public class Engine extends JexlEngine { private static final class UberspectHolder { /** The default uberspector that handles all introspection patterns. */ private static final Uberspect UBERSPECT = - new Uberspect(LogManager.getLogger(JexlEngine.class)); + new Uberspect(LogManager.getLogger(JexlEngine.class), JexlUberspect.JEXL_STRATEGY); /** Non-instantiable. */ private UberspectHolder() { @@ -137,7 +137,7 @@ public class Engine extends JexlEngine { */ public Engine(JexlBuilder conf) { JexlSandbox sandbox = conf.sandbox(); - JexlUberspect uber = conf.uberspect() == null ? getUberspect(conf.logger()) : conf.uberspect(); + JexlUberspect uber = conf.uberspect() == null ? getUberspect(conf.logger(), conf.strategy()) : conf.uberspect(); ClassLoader loader = conf.loader(); if (loader != null) { uber.setClassLoader(loader); @@ -168,13 +168,15 @@ public class Engine extends JexlEngine { * be able to use a (low level) introspector created with a given logger * instead of the default one.</p> * @param logger the logger to use for the underlying Uberspect + * @param strategy the property resolver strategy * @return Uberspect the default uberspector instance. */ - public static Uberspect getUberspect(Logger logger) { - if (logger == null || logger.equals(LogManager.getLogger(JexlEngine.class))) { + public static Uberspect getUberspect(Logger logger, JexlUberspect.ResolverStrategy strategy) { + if ((logger == null || logger.equals(LogManager.getLogger(JexlEngine.class))) + && (strategy == null || strategy == JexlUberspect.JEXL_STRATEGY)) { return UberspectHolder.UBERSPECT; } - return new Uberspect(logger); + return new Uberspect(logger, strategy); } @Override Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/IntegerRange.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/IntegerRange.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/IntegerRange.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/IntegerRange.java Sat Aug 1 14:51:49 2015 @@ -18,7 +18,6 @@ package org.apache.commons.jexl3.interna import java.lang.reflect.Array; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.NoSuchElementException; @@ -74,10 +73,10 @@ public abstract class IntegerRange imple @Override public int hashCode() { int hash = getClass().hashCode(); - //CHECKSTYLE:OFF Not magic number + //CSOFF: MagicNumber hash = 13 * hash + this.min; hash = 13 * hash + this.max; - //CHECKSTYLE:ON + //CSON: MagicNumber return hash; } Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java Sat Aug 1 14:51:49 2015 @@ -1590,6 +1590,21 @@ public class Interpreter extends ParserV } /** + * Determines the property {s,g}etter strategy to use. + * @param node the syntactic node + * @param obj the instance we are seeking the {s,g}etter from + * @return a list of resolvers, not null + */ + protected List<JexlUberspect.ResolverType> getPropertyResolvers(JexlNode node, Object obj) { + List<JexlUberspect.ResolverType> strategy = node == null + ? null + : node.jjtGetParent() instanceof ASTArrayAccess + ? JexlUberspect.MAP + : JexlUberspect.POJO; + return strategy; + } + + /** * Gets an attribute of an object. * * @param object to retrieve value from @@ -1628,9 +1643,7 @@ public class Interpreter extends ParserV } // resolve that property Exception xcause = null; - List<JexlUberspect.ResolverType> strategy = uberspect.getStrategy( - !(node != null && node.jjtGetParent() instanceof ASTArrayAccess), - object.getClass()); + List<JexlUberspect.ResolverType> strategy = getPropertyResolvers(node, object); JexlPropertyGet vg = uberspect.getPropertyGet(strategy, object, attribute); if (vg != null) { try { @@ -1692,9 +1705,7 @@ public class Interpreter extends ParserV } } Exception xcause = null; - List<JexlUberspect.ResolverType> strategy = uberspect.getStrategy( - !(node != null && node.jjtGetParent() instanceof ASTArrayAccess), - object.getClass()); + List<JexlUberspect.ResolverType> strategy = getPropertyResolvers(node, object); JexlPropertySet vs = uberspect.getPropertySet(strategy, object, attribute, value); // if we can't find an exact match, narrow the value argument and try again if (vs == null) { Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/LongRange.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/LongRange.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/LongRange.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/LongRange.java Sat Aug 1 14:51:49 2015 @@ -75,10 +75,10 @@ public abstract class LongRange implemen @Override public int hashCode() { int hash = getClass().hashCode(); - //CHECKSTYLE:OFF Not magic number + //CSOFF: MagicNumber hash = 13 * hash + (int) (this.min ^ (this.min >>> 32)); hash = 13 * hash + (int) (this.max ^ (this.max >>> 32)); - //CHECKSTYLE:ON + //CSON: MagicNumber return hash; } Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/SandboxUberspect.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/SandboxUberspect.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/SandboxUberspect.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/SandboxUberspect.java Sat Aug 1 14:51:49 2015 @@ -107,16 +107,8 @@ public final class SandboxUberspect impl * {@inheritDoc} */ @Override - public List<ResolverType> getStrategy(boolean db, Class<?> clazz) { - return db ? JexlUberspect.POJO : JexlUberspect.MAP; - } - - /** - * {@inheritDoc} - */ - @Override public JexlPropertyGet getPropertyGet(Object obj, Object identifier) { - return getPropertyGet(POJO, obj, identifier); + return getPropertyGet(null, obj, identifier); } /** @@ -138,7 +130,7 @@ public final class SandboxUberspect impl */ @Override public JexlPropertySet getPropertySet(final Object obj, final Object identifier, Object arg) { - return getPropertySet(POJO, obj, identifier, arg); + return getPropertySet(null, obj, identifier, arg); } /** Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java Sat Aug 1 14:51:49 2015 @@ -56,6 +56,8 @@ public class Uberspect implements JexlUb public static final Object TRY_FAILED = JexlEngine.TRY_FAILED; /** The logger to use for all warnings and errors. */ protected final Logger rlog; + /** The resolver strategy. */ + private final JexlUberspect.ResolverStrategy strategy; /** The introspector version. */ private final AtomicInteger version; /** The soft reference to the introspector currently in use. */ @@ -73,9 +75,11 @@ public class Uberspect implements JexlUb /** * Creates a new Uberspect. * @param runtimeLogger the logger used for all logging needs + * @param sty the resolver strategy */ - public Uberspect(Logger runtimeLogger) { + public Uberspect(Logger runtimeLogger, JexlUberspect.ResolverStrategy sty) { rlog = runtimeLogger; + strategy = sty == null? JexlUberspect.JEXL_STRATEGY : sty; ref = new SoftReference<Introspector>(null); loader = new SoftReference<ClassLoader>(getClass().getClassLoader()); operatorMap = new ConcurrentHashMap<Class<? extends JexlArithmetic>, Set<JexlOperator>>(); @@ -216,28 +220,27 @@ public class Uberspect implements JexlUb return MethodExecutor.discover(base(), obj, method, args); } - @Override - public List<ResolverType> getStrategy(boolean db, Class<?> clazz) { - //return Map.class.isAssignableFrom(clazz)? JexlUberspect.MAP : JexlUberspect.POJO; - return db ? JexlUberspect.POJO : JexlUberspect.MAP; - } +// @Override +// public List<ResolverType> getStrategy(List<ResolverType> resolvers, Object obj) { +// return strategy.apply(resolvers, obj); +// } @Override public JexlPropertyGet getPropertyGet(Object obj, Object identifier) { - return getPropertyGet(POJO, obj, identifier); + return getPropertyGet(null, obj, identifier); } @Override public JexlPropertyGet getPropertyGet( - final List<ResolverType> strategy, final Object obj, final Object identifier) { - if (strategy == null) { - throw new NullPointerException("null property resolver strategy"); - } + final List<ResolverType> resolvers, final Object obj, final Object identifier + ) { + + final List<ResolverType> actual = strategy.apply(resolvers, obj); final Class<?> claz = obj.getClass(); final String property = AbstractExecutor.castString(identifier); final Introspector is = base(); JexlPropertyGet executor = null; - for (ResolverType resolver : strategy) { + for (ResolverType resolver : actual) { switch (resolver) { case PROPERTY: // first try for a getFoo() type of property (also getfoo() ) @@ -285,20 +288,19 @@ public class Uberspect implements JexlUb @Override public JexlPropertySet getPropertySet(final Object obj, final Object identifier, final Object arg) { - return getPropertySet(POJO, obj, identifier, arg); + return getPropertySet(null, obj, identifier, arg); } @Override public JexlPropertySet getPropertySet( - final List<ResolverType> strategy, final Object obj, final Object identifier, final Object arg) { - if (strategy == null) { - throw new NullPointerException("null property resolver strategy"); - } + final List<ResolverType> resolvers, final Object obj, final Object identifier, final Object arg + ) { + final List<ResolverType> actual = strategy.apply(resolvers, obj); final Class<?> claz = obj.getClass(); final String property = AbstractExecutor.castString(identifier); final Introspector is = base(); JexlPropertySet executor = null; - for (ResolverType resolver : strategy) { + for (ResolverType resolver : actual) { switch (resolver) { case PROPERTY: // first try for a setFoo() type of property (also setfoo() ) Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlUberspect.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlUberspect.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlUberspect.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlUberspect.java Sat Aug 1 14:51:49 2015 @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Map; /** * 'Federated' introspection/reflection interface to allow JEXL introspection @@ -32,10 +33,17 @@ import java.util.List; public interface JexlUberspect { /** * The various property resolver types. - * <p>These are used to compose 'strategies' to solve properties; a strategy is an array (list) of resolver types. + * <p> * Each resolver type discovers how to set/get a property with different techniques; seeking * method names or field names, etc. - * In a strategy, these are tried in sequence and the first non-null resolver stops the search. + * <p> + * These are used through 'strategies' to solve properties; a strategy orders a list of resolver types, + * and each resolver type is tried in sequence; the first resolver that discovers a non null {s,g}etter + * stops the search. + * @see ResolverStrategy + * @see JexlUberspect#getPropertyGet + * @see JexlUberspect#getPropertySet + * @since 3.0 */ enum ResolverType { /** @@ -66,10 +74,7 @@ public interface JexlUberspect { } /** - * A resolver strategy tailored for POJOs, favors '.' over '[]'. - * This is the default strategy for getPropertyGet/getPropertySet. - * @see JexlUberspect#getPropertyGet - * @see JexlUberspect#getPropertySet + * A resolver types list tailored for POJOs, favors '.' over '[]'. */ List<ResolverType> POJO = Collections.unmodifiableList(Arrays.asList( ResolverType.PROPERTY, @@ -81,7 +86,7 @@ public interface JexlUberspect { )); /** - * A resolver strategy tailored for Maps, favors '[]' over '.'. + * A resolver types list tailored for Maps, favors '[]' over '.'. */ List<ResolverType> MAP = Collections.unmodifiableList(Arrays.asList( ResolverType.MAP, @@ -93,6 +98,60 @@ public interface JexlUberspect { )); /** + * Determine property resolution strategies. + * <p> + * To use a strategy instance, you have to set it at engine creation using + * {@link org.apache.commons.jexl3.JexlBuilder#strategy(JexlUberspect.ResolverStrategy)} + * as in:<br/> + * <code>JexlEngine jexl = new JexlBuilder().strategy(MY_STRATEGY).create();</code> + * @see ResolverType + * @since 3.0 + */ + interface ResolverStrategy { + /** + * Applies this strategy to a list of resolver types. + * <p> + * <ul>In the default implementation, the resolvers argument depends on the calling situation: + * <li>{@link #POJO} for dot operator resolution (foo.bar )</li> + * <li>{@link #MAP} for bracket operator resolution (foo['bar'])</li> + * <li>null when called from {@link #getPropertyGet(java.lang.Object, java.lang.Object) } + * or {@link #getPropertySet(java.lang.Object, java.lang.Object, java.lang.Object)}</li> + * </ul> + * + * @param resolvers candidate resolver types list + * @param obj the instance we seek to obtain a property setter/getter from, can not be null + * @return the ordered list of resolvers types, must not be null + */ + List<ResolverType> apply(List<ResolverType> resolvers, Object obj); + } + + /** + * The default strategy. + * <p> + * If the resolvers list is not null, use that list. + * Otherwise, if the object is a map, use the MAP list, otherwise use the POJO list. + */ + ResolverStrategy JEXL_STRATEGY = new ResolverStrategy() { + @Override + public List<ResolverType> apply(List<ResolverType> resolvers, Object obj) { + return resolvers != null ? resolvers : obj instanceof Map? JexlUberspect.MAP : JexlUberspect.POJO; + } + }; + + /** + * The map strategy. + * <p> + * If the object is a map, use the MAP list. + * Otherwise, if the resolvers list is not null, use that list, otherwise use the POJO list. + */ + ResolverStrategy MAP_STRATEGY = new ResolverStrategy() { + @Override + public List<ResolverType> apply(List<ResolverType> strategy, Object obj) { + return obj instanceof Map? JexlUberspect.MAP : strategy != null ? strategy : JexlUberspect.POJO; + } + }; + + /** * Sets the class loader to use. * <p>This increments the version.</p> * @param loader the class loader @@ -133,24 +192,17 @@ public interface JexlUberspect { JexlPropertyGet getPropertyGet(Object obj, Object identifier); /** - * Gets the strategy to apply for resolving properties. - * <p>Default behavior is to use POJO if db is true, MAP if db is false. - * @param db access operator flag, true for dot ('.' ) or false for bracket ('[]') - * @param clazz the property owner class - * @return the strategy - */ - List<ResolverType> getStrategy(boolean db, Class<?> clazz); - - /** * Property getter. * <p>Seeks a JexlPropertyGet apropos to an expression like <code>bar.woogie</code>.</p> - * @param strategy the ordered list of resolver types, must not be null - * @param obj the object to get the property from + * @param resolvers the list of resolver types, + * argument to {@link ResolverStrategy#apply(java.util.List, java.lang.Object) } + * @param obj the object to get the property from, + * argument to {@link ResolverStrategy#apply(java.util.List, java.lang.Object) } * @param identifier property name * @return a {@link JexlPropertyGet} or null * @since 3.0 */ - JexlPropertyGet getPropertyGet(List<ResolverType> strategy, Object obj, Object identifier); + JexlPropertyGet getPropertyGet(List<ResolverType> resolvers, Object obj, Object identifier); /** * Property setter. @@ -165,14 +217,16 @@ public interface JexlUberspect { /** * Property setter. * <p>Seeks a JelPropertySet apropos to an expression like <code>foo.bar = "geir"</code>.</p> - * @param strategy the ordered list of resolver types, must not be null - * @param obj the object to get the property from + * @param resolvers the list of resolver types, + * argument to {@link ResolverStrategy#apply(java.util.List, java.lang.Object) } + * @param obj the object to get the property from, + * argument to {@link ResolverStrategy#apply(java.util.List, java.lang.Object) } * @param identifier property name - * @param arg value to set + * @param arg value to set * @return a {@link JexlPropertySet} or null * @since 3.0 */ - JexlPropertySet getPropertySet(List<ResolverType> strategy, Object obj, Object identifier, Object arg); + JexlPropertySet getPropertySet(List<ResolverType> resolvers, Object obj, Object identifier, Object arg); /** * Gets an iterator from an object. Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java Sat Aug 1 14:51:49 2015 @@ -30,7 +30,9 @@ import javax.xml.parsers.DocumentBuilder import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.w3c.dom.Attr; import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"}) @@ -412,6 +414,54 @@ public class ArithmeticTest extends Jexl } @Test + /** + * JEXL-156. + */ + public void testMultClass() throws Exception { + JexlEngine jexl = new JexlBuilder().create(); + JexlContext jc = new MapContext(); + Object ra = jexl.createExpression("463.0d * 0.1").evaluate(jc); + Assert.assertEquals(Double.class, ra.getClass()); + Object r0 = jexl.createExpression("463.0B * 0.1").evaluate(jc); + Assert.assertEquals(java.math.BigDecimal.class, r0.getClass()); + Object r1 = jexl.createExpression("463.0B * 0.1B").evaluate(jc); + Assert.assertEquals(java.math.BigDecimal.class, r1.getClass()); + } + + public void testDivClass() throws Exception { + JexlEngine jexl = new JexlBuilder().create(); + JexlContext jc = new MapContext(); + Object ra = jexl.createExpression("463.0d / 0.1").evaluate(jc); + Assert.assertEquals(Double.class, ra.getClass()); + Object r0 = jexl.createExpression("463.0B / 0.1").evaluate(jc); + Assert.assertEquals(java.math.BigDecimal.class, r0.getClass()); + Object r1 = jexl.createExpression("463.0B / 0.1B").evaluate(jc); + Assert.assertEquals(java.math.BigDecimal.class, r1.getClass()); + } + + public void testPlusClass() throws Exception { + JexlEngine jexl = new JexlBuilder().create(); + JexlContext jc = new MapContext(); + Object ra = jexl.createExpression("463.0d + 0.1").evaluate(jc); + Assert.assertEquals(Double.class, ra.getClass()); + Object r0 = jexl.createExpression("463.0B + 0.1").evaluate(jc); + Assert.assertEquals(java.math.BigDecimal.class, r0.getClass()); + Object r1 = jexl.createExpression("463.0B + 0.1B").evaluate(jc); + Assert.assertEquals(java.math.BigDecimal.class, r1.getClass()); + } + + public void testMinusClass() throws Exception { + JexlEngine jexl = new JexlBuilder().create(); + JexlContext jc = new MapContext(); + Object ra = jexl.createExpression("463.0d - 0.1").evaluate(jc); + Assert.assertEquals(Double.class, ra.getClass()); + Object r0 = jexl.createExpression("463.0B - 0.1").evaluate(jc); + Assert.assertEquals(java.math.BigDecimal.class, r0.getClass()); + Object r1 = jexl.createExpression("463.0B - 0.1B").evaluate(jc); + Assert.assertEquals(java.math.BigDecimal.class, r1.getClass()); + } + + @Test public void testAddWithStringsLenient() throws Exception { JexlEngine jexl = new JexlBuilder().arithmetic(new JexlArithmetic(false)).create(); JexlScript script; @@ -1012,6 +1062,9 @@ public class ArithmeticTest extends Jexl } @Test + /** + * Inspired by JEXL-16{1,2}. + */ public void testXmlArithmetic() throws Exception { JexlEngine jexl = new JexlBuilder().arithmetic(new XmlArithmetic(false)).create(); JexlScript e0 = jexl.createScript("x.empty()", "x"); @@ -1052,6 +1105,22 @@ public class ArithmeticTest extends Jexl Assert.assertEquals(0, size); size = (Integer) s1.execute(null, x); Assert.assertEquals(0, size); + xml = getDocument("<node info='123'/>"); + NamedNodeMap nnm = xml.getLastChild().getAttributes(); + Attr info = (Attr) nnm.getNamedItem("info"); + Assert.assertEquals("123", info.getValue()); + + // JEXL-161 + JexlContext jc = new MapContext(); + jc.set("x", xml.getLastChild()); + final String y = "456"; + jc.set("y", y); + JexlScript s = jexl.createScript("x.attribute.info = y"); + Object r = s.execute(jc); + nnm = xml.getLastChild().getAttributes(); + info = (Attr) nnm.getNamedItem("info"); + Assert.assertEquals(y, r); + Assert.assertEquals(y, info.getValue()); } @Test Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java Sat Aug 1 14:51:49 2015 @@ -22,25 +22,14 @@ import java.math.MathContext; import java.util.HashMap; import java.util.Map; import org.apache.commons.jexl3.internal.introspection.Uberspect; -import java.io.ByteArrayInputStream; import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; //import org.apache.commons.beanutils.LazyDynaMap; /** @@ -1121,18 +1110,6 @@ public class IssuesTest extends JexlTest Assert.assertEquals("CD", value1); } - @Test - public void test156() throws Exception { - JexlEngine jexl = new Engine(); - JexlContext jc = new MapContext(); - Object ra = jexl.createExpression("463.0d * 0.1").evaluate(jc); - Assert.assertEquals(Double.class, ra.getClass()); - Object r0 = jexl.createExpression("463.0B * 0.1").evaluate(jc); - Assert.assertEquals(java.math.BigDecimal.class, r0.getClass()); - Object r1 = jexl.createExpression("463.0B * 0.1B").evaluate(jc); - Assert.assertEquals(java.math.BigDecimal.class, r1.getClass()); - } - // // // @Test @@ -1186,104 +1163,4 @@ public class IssuesTest extends JexlTest // // Assert.assertEquals(null, ((Double)e.evaluate(jc)).doubleValue(), 50d, 0d); // } - - - @Test - public void test161() throws Exception { - final JexlEngine jexl = new Engine(); - final JexlContext jc = new MapContext(); - - Document xml = getDocument("<node info='123'/>"); - NamedNodeMap nnm = xml.getLastChild().getAttributes(); - Attr info = (Attr) nnm.getNamedItem("info"); - Assert.assertEquals("123", info.getValue()); - - jc.set("x", xml.getLastChild()); - final String y = "456"; - jc.set("y", y); - JexlScript s = jexl.createScript("x.attribute.info = y"); - Object r = s.execute(jc); - nnm = xml.getLastChild().getAttributes(); - info = (Attr) nnm.getNamedItem("info"); - Assert.assertEquals(y, r); - Assert.assertEquals(y, info.getValue()); - } - - public static class XmlArithmetic extends JexlArithmetic { - public XmlArithmetic(boolean lenient) { - super(lenient); - } - public boolean empty(org.w3c.dom.Element elt) { - return !elt.hasAttributes() && !elt.hasChildNodes(); - } - } - - @Test - public void test162() throws Exception { - JexlEngine jexl = //new JexlBuilder().arithmetic(new JexlArithmetic(false)).create(); -new JexlBuilder().arithmetic(new XmlArithmetic(false)).create(); - JexlScript s0 = jexl.createScript("x.empty()", "x"); - Document xml; - Node x; - Boolean r; - xml = getDocument("<node info='123'/>"); - x = xml.getLastChild(); - r = (Boolean) s0.execute(null, x); - Assert.assertFalse(r); - xml = getDocument("<node>some content</node>"); - x = xml.getLastChild(); - r = (Boolean) s0.execute(null, x); - Assert.assertFalse(r); - xml = getDocument("<node/>"); - x = xml.getLastChild(); - r = (Boolean) s0.execute(null, x); - Assert.assertTrue(r); - } - - private static Document getDocument(String xml) throws IOException, SAXException, ParserConfigurationException { - DocumentBuilder xmlBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - InputStream stringInputStream = new ByteArrayInputStream(xml.getBytes("UTF-8")); - return xmlBuilder.parse(stringInputStream); - } - - - @Test - public void test171() throws Exception { - final JexlEngine jexl = new Engine(); - Object result; - Map<String, Object> i = new HashMap<String, Object>(); - - i.put("class", 42); - result = jexl.createScript("i['class'] ", "i").execute((JexlContext)null, i); - Assert.assertEquals(42, result); - result = jexl.createScript("i['class'] = 28", "i").execute((JexlContext)null, i); - Assert.assertEquals(28, result); - Assert.assertEquals(28, i.get("class")); - result = jexl.createScript("i.class", "i").execute((JexlContext)null, i); - Assert.assertEquals(java.util.HashMap.class, result); - result = jexl.createScript("i.'class'", "i").execute((JexlContext)null, i); - Assert.assertEquals(java.util.HashMap.class, result); - - i.put("size", 4242); - result = jexl.createScript("i['size'] ", "i").execute((JexlContext)null, i); - Assert.assertEquals(4242 ,result); - result = jexl.createScript("i['size'] = 2828", "i").execute((JexlContext)null, i); - Assert.assertEquals(2828, result); - Assert.assertEquals(2828, i.get("size")); - result = jexl.createScript("i.'size'", "i").execute((JexlContext)null, i); - Assert.assertEquals(2828, result); - result = jexl.createScript("size i", "i").execute((JexlContext)null, i); - Assert.assertEquals(2, result); - - i.put("empty", 424242); - result = jexl.createScript("i['empty'] ", "i").execute((JexlContext)null, i); - Assert.assertEquals(424242, result); - result = jexl.createScript("i['empty'] = 282828", "i").execute((JexlContext)null, i); - Assert.assertEquals(282828, result); - Assert.assertEquals(282828, i.get("empty")); - result = jexl.createScript("i.'empty'", "i").execute((JexlContext)null, i); - Assert.assertNotEquals(282828, result); - result = jexl.createScript("empty i", "i").execute((JexlContext)null, i); - Assert.assertFalse((Boolean) result); - } } Added: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/StrategyTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/StrategyTest.java?rev=1693711&view=auto ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/StrategyTest.java (added) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/StrategyTest.java Sat Aug 1 14:51:49 2015 @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jexl3; + +import org.apache.commons.jexl3.internal.Engine; +import org.apache.commons.jexl3.introspection.JexlUberspect; +import java.util.HashMap; +import java.util.Map; +import org.junit.Assert; +import org.junit.Test; + +/** + * Test cases for the if statement. + * + * @since 1.1 + */ +@SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"}) +public class StrategyTest extends JexlTestCase { + public StrategyTest() { + super("StrategyTest"); + } + + + @Test + public void testJexlStrategy() throws Exception { + final JexlEngine jexl = new Engine(); + run171(jexl, true); + } + + @Test + public void testMapStrategy() throws Exception { + final JexlEngine jexl = new JexlBuilder().strategy(JexlUberspect.MAP_STRATEGY).create(); + run171(jexl, false); + } + + public void run171(JexlEngine jexl, boolean std) throws Exception { + Object result; + Map<String, Object> i = new HashMap<String, Object>(); + + i.put("class", 42); + result = jexl.createScript("i['class'] ", "i").execute((JexlContext)null, i); + Assert.assertEquals(42, result); + result = jexl.createScript("i['class'] = 28", "i").execute((JexlContext)null, i); + Assert.assertEquals(28, result); + Assert.assertEquals(28, i.get("class")); + result = jexl.createScript("i.class", "i").execute((JexlContext)null, i); + if (std) { + Assert.assertEquals(java.util.HashMap.class, result); + } else { + Assert.assertEquals(28, result); + } + result = jexl.createScript("i.'class'", "i").execute((JexlContext)null, i); + if (std) { + Assert.assertEquals(java.util.HashMap.class, result); + } else { + Assert.assertEquals(28, result); + } + + i.put("size", 4242); + result = jexl.createScript("i['size'] ", "i").execute((JexlContext)null, i); + Assert.assertEquals(4242 ,result); + result = jexl.createScript("i['size'] = 2828", "i").execute((JexlContext)null, i); + Assert.assertEquals(2828, result); + Assert.assertEquals(2828, i.get("size")); + result = jexl.createScript("i.'size'", "i").execute((JexlContext)null, i); + Assert.assertEquals(2828, result); + result = jexl.createScript("size i", "i").execute((JexlContext)null, i); + Assert.assertEquals(2, result); + + i.put("empty", 424242); + result = jexl.createScript("i['empty'] ", "i").execute((JexlContext)null, i); + Assert.assertEquals(424242, result); + result = jexl.createScript("i['empty'] = 282828", "i").execute((JexlContext)null, i); + Assert.assertEquals(282828, result); + Assert.assertEquals(282828, i.get("empty")); + result = jexl.createScript("i.'empty'", "i").execute((JexlContext)null, i); + if (std) { + Assert.assertNotEquals(282828, result); + } else { + Assert.assertEquals(282828, result); + } + result = jexl.createScript("empty i", "i").execute((JexlContext)null, i); + Assert.assertFalse((Boolean) result); + } +} \ No newline at end of file Propchange: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/StrategyTest.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/introspection/DiscoveryTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/introspection/DiscoveryTest.java?rev=1693711&r1=1693710&r2=1693711&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/introspection/DiscoveryTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/introspection/DiscoveryTest.java Sat Aug 1 14:51:49 2015 @@ -104,7 +104,7 @@ public class DiscoveryTest extends JexlT @Test public void testBeanIntrospection() throws Exception { - Uberspect uber = Engine.getUberspect(null); + Uberspect uber = Engine.getUberspect(null,null); Bean bean = new Bean("JEXL", "LXEJ"); JexlPropertyGet get = uber.getPropertyGet(bean, "value"); @@ -133,7 +133,7 @@ public class DiscoveryTest extends JexlT @Test public void testDuckIntrospection() throws Exception { - Uberspect uber = Engine.getUberspect(null); + Uberspect uber = Engine.getUberspect(null,null); Duck duck = new Duck("JEXL", "LXEJ"); JexlPropertyGet get = uber.getPropertyGet(duck, "value"); @@ -161,7 +161,7 @@ public class DiscoveryTest extends JexlT @Test public void testListIntrospection() throws Exception { - Uberspect uber = Engine.getUberspect(null); + Uberspect uber = Engine.getUberspect(null,null); List<Object> list = new ArrayList<Object>(); list.add("LIST"); list.add("TSIL"); @@ -192,7 +192,7 @@ public class DiscoveryTest extends JexlT @Test public void testMapIntrospection() throws Exception { - Uberspect uber = Engine.getUberspect(null); + Uberspect uber = Engine.getUberspect(null,null); Map<String, Object> map = new HashMap<String, Object>(); map.put("value", "MAP"); map.put("eulav", "PAM");