You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2015/07/27 12:02:50 UTC

svn commit: r1692852 [1/3] - in /commons/proper/jexl/trunk/src: main/java/org/apache/commons/jexl3/ main/java/org/apache/commons/jexl3/internal/ main/java/org/apache/commons/jexl3/internal/introspection/ main/java/org/apache/commons/jexl3/introspection...

Author: henrib
Date: Mon Jul 27 10:02:49 2015
New Revision: 1692852

URL: http://svn.apache.org/r1692852
Log:
JEXL:
JEXL-170: implemented assignment operators.

Added:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlOperator.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Operators.java   (with props)
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SideEffectTest.java   (with props)
Modified:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.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/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/Uberspect.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlUberspect.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
    commons/proper/jexl/trunk/src/site/xdoc/changes.xml
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.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/ArrayAccessTest.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/junit/Asserter.java

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java?rev=1692852&r1=1692851&r2=1692852&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java Mon Jul 27 10:02:49 2015
@@ -17,7 +17,7 @@
 package org.apache.commons.jexl3;
 
 import org.apache.commons.jexl3.introspection.JexlMethod;
-
+import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.math.MathContext;
@@ -26,9 +26,12 @@ import java.util.Map;
 import java.util.regex.Pattern;
 
 /**
- * Perform arithmetic.
+ * Perform arithmetic, implements JexlOperator methods.
+ * <p>
+ * This is the class to derive to implement new operator behaviors.
+ * </p>
  * <p>
- * The 5 arithmetic operators (+, - , *, /, %) follow the same evaluation rules regarding their arguments.
+ * The 5 base arithmetic operators (+, - , *, /, %) follow the same evaluation rules regarding their arguments.
  * </p>
  * <ol>
  * <li>If both are null, result is 0</li>
@@ -42,140 +45,11 @@ import java.util.regex.Pattern;
  * </ol>
  * </li>
  * </ol>
- * Note that the only exception thrown by JexlArithmetic is ArithmeticException.
+ * Note that the only exception thrown by JexlArithmetic is and must be ArithmeticException.
+ * @see JexlOperator
  * @since 2.0
  */
 public class JexlArithmetic {
-    /**
-     * The overload-able operators.
-     * Note that logical and (ie &amp;&amp;) and logical or (ie ||) are not in this list to avoid breaking
-     * their shortcut semantics.
-     * @since 3.0
-     */
-    public enum Operator {
-        /** add(x, y). *//** add(x, y). */
-        ADD("+", "add", 2),
-        /** subtract(x, y). */
-        SUBTRACT("-", "subtract", 2),
-        /** multiply(x, y). */
-        MULTIPLY("*", "multiply", 2),
-        /** divide(x, y). */
-        DIVIDE("/", "divide", 2),
-        /** mod(x, y). */
-        MOD("%", "mod", 2),
-        /** bitwiseAnd(x, y). */
-        AND("&", "bitwiseAnd", 2),
-        /** bitwiseOr(x, y). */
-        OR("|", "bitwiseOr", 2),
-        /** bitwiseXor(x, y). */
-        XOR("^", "bitwiseXor", 2),
-        /** logicalNot(x). */
-        NOT("!", "logicalNot", 1),
-        /** bitiwiseComplement(x). */
-        COMPLEMENT("~", "bitwiseComplement", 1),
-        /** equals(x, y). */
-        EQ("==", "equals", 2),
-        /** lessThan(x, y). */
-        LT("<", "lessThan", 2),
-        /** lessThanOrEqual(x, y). */
-        LTE("<=", "lessThanOrEqual", 2),
-        /** greaterThan(x, y). */
-        GT(">", "greaterThan", 2),
-        /** greaterThanOrEqual(x, y). */
-        GTE(">=", "greaterThanOrEqual", 2),
-        /** negate(x). */
-        NEGATE("-", "negate", 1),
-        /** contains(x). */
-        CONTAINS("=~", "contains", 2),
-        /** startsWith(x, y). */
-        STARTSWITH("=^", "startsWith", 2),
-        /** endsWith(x, y). */
-        ENDSWITH("=$", "endsWith", 2),
-        /** empty(x). */
-        EMPTY("empty", "empty", 1),
-        /** size(x). */
-        SIZE("size", "size", 1);
-
-        /**
-         * The operator symbol.
-         */
-        private final String operator;
-        /**
-         * The associated operator method name.
-         */
-        private final String methodName;
-        /**
-         * The method arity.
-         */
-        private final int arity;
-
-        /**
-         * Creates an operator.
-         * @param o the operator name
-         * @param m the method name associated to this operator in a JexlArithmetic
-         * @param argc the number of parameters for the method
-         */
-        Operator(String o, String m, int argc) {
-            this.operator = o;
-            this.methodName = m;
-            this.arity = argc;
-        }
-
-        /**
-         * Gets this operator symbol.
-         * @return the symbol
-         */
-        public final String getOperatorSymbol() {
-            return operator;
-        }
-
-        /**
-         * Gets this operator method name in a JexlArithmetic.
-         * @return the method name
-         */
-        public final String getMethodName() {
-            return methodName;
-        }
-
-        /**
-         * Gets this operator number of parameters.
-         * @return the method arity
-         */
-        public int getArity() {
-            return arity;
-        }
-    }
-
-    /**
-     * The interface that uberspects JexlArithmetic classes.
-     * <p>This allows overloaded operator methods discovery.
-     */
-    public interface Uberspect {
-        /**
-         * Checks whether this uberspect has overloads for a given operator.
-         * @param operator the operator to check
-         * @return true if an overload exists, false otherwise
-         */
-        boolean overloads(JexlArithmetic.Operator operator);
-
-        /**
-         * Gets the most specific method for a monadic operator.
-         * @param operator the operator
-         * @param arg the argument
-         * @return the most specific method or null if no specific override could be found
-         */
-        JexlMethod getOperator(JexlArithmetic.Operator operator, Object arg);
-
-        /**
-         * Gets the most specific method for a diadic operator.
-         * @param operator the operator
-         * @param lhs the left hand side argument
-         * @param rhs the right hand side argument
-         * @return the most specific method or null if no specific override could be found
-         */
-        JexlMethod getOperator(JexlArithmetic.Operator operator, Object lhs, Object rhs);
-    }
-
     /** Marker class for null operand exceptions. */
     public static class NullOperand extends ArithmeticException {}
     /** Double.MAX_VALUE as BigDecimal. */
@@ -242,6 +116,36 @@ public class JexlArithmetic {
     }
 
     /**
+     * The interface that uberspects JexlArithmetic classes.
+     * <p>This allows overloaded operator methods discovery.
+     */
+    public interface Uberspect {
+        /**
+         * Checks whether this uberspect has overloads for a given operator.
+         * @param operator the operator to check
+         * @return true if an overload exists, false otherwise
+         */
+        boolean overloads(JexlOperator operator);
+
+        /**
+         * Gets the most specific method for a monadic operator.
+         * @param operator the operator
+         * @param arg      the argument
+         * @return the most specific method or null if no specific override could be found
+         */
+        JexlMethod getOperator(JexlOperator operator, Object arg);
+
+        /**
+         * Gets the most specific method for a diadic operator.
+         * @param operator the operator
+         * @param lhs      the left hand side argument
+         * @param rhs      the right hand side argument
+         * @return the most specific method or null if no specific override could be found
+         */
+        JexlMethod getOperator(JexlOperator operator, Object lhs, Object rhs);
+    }
+
+    /**
      * Helper interface used when creating an array literal.
      * <p>The default implementation creates an array and attempts to type it strictly.
      * <ul>
@@ -343,7 +247,7 @@ public class JexlArithmetic {
         final long lfrom = toLong(from);
         final long lto = toLong(to);
         if ((lfrom >= Integer.MIN_VALUE && lfrom <= Integer.MAX_VALUE)
-            && (lto >= Integer.MIN_VALUE && lto <= Integer.MAX_VALUE)) {
+                && (lto >= Integer.MIN_VALUE && lto <= Integer.MAX_VALUE)) {
             return org.apache.commons.jexl3.internal.IntegerRange.create((int) lfrom, (int) lto);
         } else {
             return org.apache.commons.jexl3.internal.LongRange.create(lfrom, lto);
@@ -352,8 +256,7 @@ public class JexlArithmetic {
 
     /**
      * Checks whether this JexlArithmetic instance
-     * strictly considers null as an error when used as operand unexpectedly
-     * and forces add(...) to concatenate strings (instead of attempting number conversion).
+     * strictly considers null as an error when used as operand unexpectedly.
      * @return true if strict, false if lenient
      */
     public boolean isStrict() {
@@ -399,7 +302,7 @@ public class JexlArithmetic {
         if (isStrict()) {
             throw new NullOperand();
         }
-        return Integer.valueOf(0);
+        return 0;
     }
 
     /**
@@ -517,9 +420,9 @@ public class JexlArithmetic {
                     if (narrowAccept(narrow, Integer.class)
                             && l <= Integer.MAX_VALUE
                             && l >= Integer.MIN_VALUE) {
-                        return Integer.valueOf((int) l);
+                        return (int) l;
                     } else if (narrowAccept(narrow, Long.class)) {
-                        return Long.valueOf(l);
+                        return l;
                     }
                 } catch (ArithmeticException xa) {
                     // ignore, no exact value possible
@@ -531,7 +434,7 @@ public class JexlArithmetic {
             if (narrowAccept(narrow, Float.class)
                     && value <= Float.MAX_VALUE
                     && value >= Float.MIN_VALUE) {
-                result = Float.valueOf(result.floatValue());
+                result = result.floatValue();
             }
             // else it fits in a double only
         } else {
@@ -548,15 +451,15 @@ public class JexlArithmetic {
                     && value <= Byte.MAX_VALUE
                     && value >= Byte.MIN_VALUE) {
                 // it will fit in a byte
-                result = Byte.valueOf((byte) value);
+                result = (byte) value;
             } else if (narrowAccept(narrow, Short.class)
                     && value <= Short.MAX_VALUE
                     && value >= Short.MIN_VALUE) {
-                result = Short.valueOf((short) value);
+                result = (short) value;
             } else if (narrowAccept(narrow, Integer.class)
                     && value <= Integer.MAX_VALUE
                     && value >= Integer.MIN_VALUE) {
-                result = Integer.valueOf((int) value);
+                result = (int) value;
             }
             // else it fits in a long
         }
@@ -587,9 +490,9 @@ public class JexlArithmetic {
             if (!(lhs instanceof Long || rhs instanceof Long)
                     && l <= Integer.MAX_VALUE
                     && l >= Integer.MIN_VALUE) {
-                return Integer.valueOf((int) l);
+                return (int) l;
             }
-            return Long.valueOf(l);
+            return l;
         }
         return bigi;
     }
@@ -609,9 +512,9 @@ public class JexlArithmetic {
                 long l = bigd.longValueExact();
                 // coerce to int when possible (int being so often used in method parms)
                 if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) {
-                    return Integer.valueOf((int) l);
+                    return (int) l;
                 } else {
-                    return Long.valueOf(l);
+                    return l;
                 }
             } catch (ArithmeticException xa) {
                 // ignore, no exact value possible
@@ -648,8 +551,8 @@ public class JexlArithmetic {
      * If any numeric add fails on coercion to the appropriate type,
      * treat as Strings and do concatenation.
      * </p>
-     * @param left  first value
-     * @param right second value
+     * @param left  left argument
+     * @param right  right argument
      * @return left + right.
      */
     public Object add(Object left, Object right) {
@@ -672,7 +575,7 @@ public class JexlArithmetic {
                 if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
                     double l = toDouble(left);
                     double r = toDouble(right);
-                    return new Double(l + r);
+                    return l + r;
                 }
                 // otherwise treat as integers
                 BigInteger l = toBigInteger(left);
@@ -680,7 +583,6 @@ public class JexlArithmetic {
                 BigInteger result = l.add(r);
                 return narrowBigInteger(left, right, result);
             } catch (java.lang.NumberFormatException nfe) {
-                // Well, use strings!
                 if (left == null || right == null) {
                     controlNullOperand();
                 }
@@ -691,8 +593,8 @@ public class JexlArithmetic {
 
     /**
      * Divide the left value by the right.
-     * @param left  first value
-     * @param right second value
+     * @param left  left argument
+     * @param right  right argument
      * @return left / right
      * @throws ArithmeticException if right == 0
      */
@@ -717,7 +619,7 @@ public class JexlArithmetic {
             if (r == 0.0) {
                 throw new ArithmeticException("/");
             }
-            return new Double(l / r);
+            return l / r;
         }
         // otherwise treat as integers
         BigInteger l = toBigInteger(left);
@@ -730,10 +632,10 @@ public class JexlArithmetic {
     }
 
     /**
-     * left value mod right.
-     * @param left  first value
-     * @param right second value
-     * @return left mod right
+     * left value modulo right.
+     * @param left  left argument
+     * @param right  right argument
+     * @return left % right
      * @throws ArithmeticException if right == 0.0
      */
     public Object mod(Object left, Object right) {
@@ -757,7 +659,7 @@ public class JexlArithmetic {
             if (r == 0.0) {
                 throw new ArithmeticException("%");
             }
-            return new Double(l % r);
+            return l % r;
         }
         // otherwise treat as integers
         BigInteger l = toBigInteger(left);
@@ -771,8 +673,8 @@ public class JexlArithmetic {
 
     /**
      * Multiply the left value by the right.
-     * @param left  first value
-     * @param right second value
+     * @param left  left argument
+     * @param right  right argument
      * @return left * right.
      */
     public Object multiply(Object left, Object right) {
@@ -790,7 +692,7 @@ public class JexlArithmetic {
         if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
             double l = toDouble(left);
             double r = toDouble(right);
-            return new Double(l * r);
+            return l * r;
         }
         // otherwise treat as integers
         BigInteger l = toBigInteger(left);
@@ -801,8 +703,8 @@ public class JexlArithmetic {
 
     /**
      * Subtract the right value from the left.
-     * @param left  first value
-     * @param right second value
+     * @param left  left argument
+     * @param right  right argument
      * @return left - right.
      */
     public Object subtract(Object left, Object right) {
@@ -820,7 +722,7 @@ public class JexlArithmetic {
         if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
             double l = toDouble(left);
             double r = toDouble(right);
-            return new Double(l - r);
+            return l - r;
         }
         // otherwise treat as integers
         BigInteger l = toBigInteger(left);
@@ -836,69 +738,65 @@ public class JexlArithmetic {
      */
     public Object negate(Object val) {
         if (val instanceof Integer) {
-            int valueAsInt = ((Integer) val).intValue();
-            return Integer.valueOf(-valueAsInt);
+            return -((Integer) val);
         } else if (val instanceof Double) {
-            double valueAsDouble = ((Double) val).doubleValue();
-            return new Double(-valueAsDouble);
+            return - ((Double) val);
         } else if (val instanceof Long) {
-            long valueAsLong = -((Long) val).longValue();
-            return Long.valueOf(valueAsLong);
+            return -((Long) val);
         } else if (val instanceof BigDecimal) {
-            BigDecimal valueAsBigD = (BigDecimal) val;
-            return valueAsBigD.negate();
+            return ((BigDecimal) val).negate();
         } else if (val instanceof BigInteger) {
-            BigInteger valueAsBigI = (BigInteger) val;
-            return valueAsBigI.negate();
+            return ((BigInteger) val).negate();
         } else if (val instanceof Float) {
-            float valueAsFloat = ((Float) val).floatValue();
-            return new Float(-valueAsFloat);
+            return -((Float) val);
         } else if (val instanceof Short) {
-            short valueAsShort = ((Short) val).shortValue();
-            return Short.valueOf((short) -valueAsShort);
+            return (short) -((Short) val);
         } else if (val instanceof Byte) {
-            byte valueAsByte = ((Byte) val).byteValue();
-            return Byte.valueOf((byte) -valueAsByte);
+            return (byte) -((Byte) val);
         } else if (val instanceof Boolean) {
-            return ((Boolean) val).booleanValue() ? Boolean.FALSE : Boolean.TRUE;
+            return ((Boolean) val) ? Boolean.FALSE : Boolean.TRUE;
         }
         throw new ArithmeticException("Object negation:(" + val + ")");
     }
 
     /**
-     * Test if left matches right.
-     *
-     * @param left  first value
-     * @param right second value
+     * Test if left contains right (right matches/in left).
+     * <p>Beware that this method arguments are the opposite of the operator arguments.
+     * 'x in y' means 'y contains x'.</p>
+     * @param container the container
+     * @param value the value
      * @return test result or null if there is no arithmetic solution
      */
-    public Boolean contains(Object left, Object right) {
-        if (left == null && right == null) {
+    public Boolean contains(Object container, Object value) {
+        if (value == null && container == null) {
             //if both are null L == R
             return true;
         }
-        if (left == null || right == null) {
+        if (value == null || container == null) {
             // we know both aren't null, therefore L != R
             return false;
         }
         // use arithmetic / pattern matching ?
-        if (right instanceof java.util.regex.Pattern) {
-            return ((java.util.regex.Pattern) right).matcher(left.toString()).matches();
+        if (container instanceof java.util.regex.Pattern) {
+            return ((java.util.regex.Pattern) container).matcher(value.toString()).matches();
         }
-        if ( right instanceof String) {
-            return left.toString().matches(right.toString());
+        if (container instanceof String) {
+            return value.toString().matches(container.toString());
         }
         // try contains on map key
-        if (right instanceof Map<?, ?>) {
-            return ((Map<?, ?>) right).containsKey(left);
+        if (container instanceof Map<?, ?>) {
+            if (value instanceof Map<?, ?>) {
+                return ((Map<?, ?>) container).keySet().containsAll(((Map<?, ?>) value).keySet());
+            }
+            return ((Map<?, ?>) container).containsKey(value);
         }
         // try contains on collection
-        if (right instanceof Collection<?>) {
-            if (left instanceof Collection<?>) {
-                return ((Collection<?>) right).containsAll((Collection<?>) left);
+        if (container instanceof Collection<?>) {
+            if (value instanceof Collection<?>) {
+                return ((Collection<?>) container).containsAll((Collection<?>) value);
             }
             // left in right ? <=> right.contains(left) ?
-            return ((Collection<?>) right).contains(left);
+            return ((Collection<?>) container).contains(value);
         }
         return null;
     }
@@ -906,9 +804,9 @@ public class JexlArithmetic {
     /**
      * Test if left ends with right.
      *
-     * @param left  first value
-     * @param right second value
-     * @return test result or null if there is no arithmetic solution
+     * @param left  left argument
+     * @param right  right argument
+     * @return left $= right if there is no arithmetic solution
      */
     public Boolean endsWith(Object left, Object right) {
         if (left == null && right == null) {
@@ -928,9 +826,9 @@ public class JexlArithmetic {
     /**
      * Test if left starts with right.
      *
-     * @param left  first value
-     * @param right second value
-     * @return test result or null if there is no arithmetic solution
+     * @param left  left argument
+     * @param right  right argument
+     * @return left ^= right or null if there is no arithmetic solution
      */
     public Boolean startsWith(Object left, Object right) {
         if (left == null && right == null) {
@@ -948,15 +846,64 @@ public class JexlArithmetic {
     }
 
     /**
+     * Check for emptyness of various types: Number, Collection, Array, Map, String.
+     *
+     * @param object the object to check the emptyness of
+     * @return the boolean or null of there is no arithmetic solution
+     */
+    public Boolean isEmpty(Object object) {
+        if (object instanceof Number) {
+            double d = ((Number) object).doubleValue();
+            return Double.isNaN(d) || d == 0.d ? Boolean.TRUE : Boolean.FALSE;
+        }
+        if (object instanceof String) {
+            return "".equals(object) ? Boolean.TRUE : Boolean.FALSE;
+        }
+        if (object.getClass().isArray()) {
+            return Array.getLength(object) == 0 ? Boolean.TRUE : Boolean.FALSE;
+        }
+        if (object instanceof Collection<?>) {
+            return ((Collection<?>) object).isEmpty() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        // Map isn't a collection
+        if (object instanceof Map<?, ?>) {
+            return ((Map<?, ?>) object).isEmpty() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return null;
+    }
+
+    /**
+     * Calculate the <code>size</code> of various types: Collection, Array, Map, String.
+     *
+     * @param object the object to get the size of
+     * @return the size of object or null if there is no arithmetic solution
+     */
+    public Integer size(Object object) {
+        if (object instanceof String) {
+            return ((String) object).length();
+        }
+        if (object.getClass().isArray()) {
+            return Array.getLength(object);
+        }
+        if (object instanceof Collection<?>) {
+            return ((Collection<?>) object).size();
+        }
+        if (object instanceof Map<?, ?>) {
+            return ((Map<?, ?>) object).size();
+        }
+        return null;
+    }
+
+    /**
      * Performs a bitwise and.
      * @param left  the left operand
      * @param right the right operator
      * @return left &amp; right
      */
-    public Object bitwiseAnd(Object left, Object right) {
+    public Object and(Object left, Object right) {
         long l = toLong(left);
         long r = toLong(right);
-        return Long.valueOf(l & r);
+        return l & r;
     }
 
     /**
@@ -965,22 +912,22 @@ public class JexlArithmetic {
      * @param right the right operator
      * @return left | right
      */
-    public Object bitwiseOr(Object left, Object right) {
+    public Object or(Object left, Object right) {
         long l = toLong(left);
         long r = toLong(right);
-        return Long.valueOf(l | r);
+        return l | r;
     }
 
     /**
      * Performs a bitwise xor.
      * @param left  the left operand
      * @param right the right operator
-     * @return left right
+     * @return left ^ right
      */
-    public Object bitwiseXor(Object left, Object right) {
+    public Object xor(Object left, Object right) {
         long l = toLong(left);
         long r = toLong(right);
-        return Long.valueOf(l ^ r);
+        return l ^ r;
     }
 
     /**
@@ -988,9 +935,9 @@ public class JexlArithmetic {
      * @param val the operand
      * @return ~val
      */
-    public Object bitwiseComplement(Object val) {
+    public Object complement(Object val) {
         long l = toLong(val);
-        return Long.valueOf(~l);
+        return ~l;
     }
 
     /**
@@ -998,7 +945,7 @@ public class JexlArithmetic {
      * @param val the operand
      * @return !val
      */
-    public Object logicalNot(Object val) {
+    public Object not(Object val) {
         return toBoolean(val) ? Boolean.FALSE : Boolean.TRUE;
     }
 
@@ -1069,9 +1016,9 @@ public class JexlArithmetic {
     /**
      * Test if left and right are equal.
      *
-     * @param left  first value
-     * @param right second value
-     * @return test result.
+     * @param left  left argument
+     * @param right right argument
+     * @return the test result
      */
     public boolean equals(Object left, Object right) {
         if (left == right) {
@@ -1088,9 +1035,9 @@ public class JexlArithmetic {
     /**
      * Test if left &lt; right.
      *
-     * @param left  first value
-     * @param right second value
-     * @return test result.
+     * @param left  left argument
+     * @param right right argument
+     * @return the test result
      */
     public boolean lessThan(Object left, Object right) {
         if ((left == right) || (left == null) || (right == null)) {
@@ -1104,9 +1051,9 @@ public class JexlArithmetic {
     /**
      * Test if left &gt; right.
      *
-     * @param left  first value
-     * @param right second value
-     * @return test result.
+     * @param left  left argument
+     * @param right right argument
+     * @return the test result
      */
     public boolean greaterThan(Object left, Object right) {
         if ((left == right) || left == null || right == null) {
@@ -1119,9 +1066,9 @@ public class JexlArithmetic {
     /**
      * Test if left &lt;= right.
      *
-     * @param left  first value
-     * @param right second value
-     * @return test result.
+     * @param left  left argument
+     * @param right right argument
+     * @return the test result
      */
     public boolean lessThanOrEqual(Object left, Object right) {
         if (left == right) {
@@ -1136,9 +1083,9 @@ public class JexlArithmetic {
     /**
      * Test if left &gt;= right.
      *
-     * @param left  first value
-     * @param right second value
-     * @return test result.
+     * @param left  left argument
+     * @param right right argument
+     * @return the test result
      */
     public boolean greaterThanOrEqual(Object left, Object right) {
         if (left == right) {
@@ -1154,7 +1101,7 @@ public class JexlArithmetic {
      * Coerce to a primitive boolean.
      * <p>Double.NaN, null, "false" and empty string coerce to false.</p>
      *
-     * @param val Object to be coerced.
+     * @param val value to coerce
      * @return the boolean value if coercion is possible, true if value was not null.
      */
     public boolean toBoolean(Object val) {
@@ -1162,7 +1109,7 @@ public class JexlArithmetic {
             controlNullOperand();
             return false;
         } else if (val instanceof Boolean) {
-            return ((Boolean) val).booleanValue();
+            return ((Boolean) val);
         } else if (val instanceof Number) {
             double number = toDouble(val);
             return !Double.isNaN(number) && number != 0.d;
@@ -1180,9 +1127,9 @@ public class JexlArithmetic {
      * <p>Double.NaN, null and empty string coerce to zero.</p>
      * <p>Boolean false is 0, true is 1.</p>
      *
-     * @param val Object to be coerced.
-     * @return The int coerced value.
-     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
+     * @param val value to coerce
+     * @return the value coerced to int
+     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible
      */
     public int toInteger(Object val) {
         if (val == null) {
@@ -1190,7 +1137,7 @@ public class JexlArithmetic {
             return 0;
         } else if (val instanceof Double) {
             Double dval = (Double) val;
-            if (Double.isNaN(dval.doubleValue())) {
+            if (Double.isNaN(dval)) {
                 return 0;
             } else {
                 return dval.intValue();
@@ -1203,9 +1150,9 @@ public class JexlArithmetic {
             }
             return Integer.parseInt((String) val);
         } else if (val instanceof Boolean) {
-            return ((Boolean) val).booleanValue() ? 1 : 0;
+            return ((Boolean) val) ? 1 : 0;
         } else if (val instanceof Character) {
-            return ((Character) val).charValue();
+            return ((Character) val);
         }
 
         throw new ArithmeticException("Integer coercion: "
@@ -1217,9 +1164,9 @@ public class JexlArithmetic {
      * <p>Double.NaN, null and empty string coerce to zero.</p>
      * <p>Boolean false is 0, true is 1.</p>
      *
-     * @param val Object to be coerced.
-     * @return The long coerced value.
-     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
+     * @param val value to coerce
+     * @return the value coerced to long
+     * @throws ArithmeticException if value is null and mode is strict or if coercion is not possible
      */
     public long toLong(Object val) {
         if (val == null) {
@@ -1227,7 +1174,7 @@ public class JexlArithmetic {
             return 0L;
         } else if (val instanceof Double) {
             Double dval = (Double) val;
-            if (Double.isNaN(dval.doubleValue())) {
+            if (Double.isNaN(dval)) {
                 return 0L;
             } else {
                 return dval.longValue();
@@ -1241,9 +1188,9 @@ public class JexlArithmetic {
                 return Long.parseLong((String) val);
             }
         } else if (val instanceof Boolean) {
-            return ((Boolean) val).booleanValue() ? 1L : 0L;
+            return ((Boolean) val) ? 1L : 0L;
         } else if (val instanceof Character) {
-            return ((Character) val).charValue();
+            return ((Character) val);
         }
 
         throw new ArithmeticException("Long coercion: "
@@ -1256,8 +1203,8 @@ public class JexlArithmetic {
      * <p>Boolean false is 0, true is 1.</p>
      *
      * @param val the object to be coerced.
-     * @return a BigDecimal.
-     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
+     * @return a BigDecimal
+     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible
      */
     public BigInteger toBigInteger(Object val) {
         if (val == null) {
@@ -1267,7 +1214,7 @@ public class JexlArithmetic {
             return (BigInteger) val;
         } else if (val instanceof Double) {
             Double dval = (Double) val;
-            if (Double.isNaN(dval.doubleValue())) {
+            if (Double.isNaN(dval)) {
                 return BigInteger.ZERO;
             } else {
                 return BigInteger.valueOf(dval.longValue());
@@ -1277,7 +1224,7 @@ public class JexlArithmetic {
         } else if (val instanceof Number) {
             return BigInteger.valueOf(((Number) val).longValue());
         } else if (val instanceof Boolean) {
-            return BigInteger.valueOf(((Boolean) val).booleanValue() ? 1L : 0L);
+            return BigInteger.valueOf(((Boolean) val) ? 1L : 0L);
         } else if (val instanceof String) {
             String string = (String) val;
             if ("".equals(string)) {
@@ -1286,7 +1233,7 @@ public class JexlArithmetic {
                 return new BigInteger(string);
             }
         } else if (val instanceof Character) {
-            int i = ((Character) val).charValue();
+            int i = ((Character) val);
             return BigInteger.valueOf(i);
         }
 
@@ -1301,7 +1248,7 @@ public class JexlArithmetic {
      *
      * @param val the object to be coerced.
      * @return a BigDecimal.
-     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
+     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible
      */
     public BigDecimal toBigDecimal(Object val) {
         if (val instanceof BigDecimal) {
@@ -1310,7 +1257,7 @@ public class JexlArithmetic {
             controlNullOperand();
             return BigDecimal.ZERO;
         } else if (val instanceof Double) {
-            if (Double.isNaN(((Double) val).doubleValue())) {
+            if (Double.isNaN(((Double) val))) {
                 return BigDecimal.ZERO;
             } else {
                 return roundBigDecimal(new BigDecimal(val.toString(), getMathContext()));
@@ -1318,7 +1265,7 @@ public class JexlArithmetic {
         } else if (val instanceof Number) {
             return roundBigDecimal(new BigDecimal(val.toString(), getMathContext()));
         } else if (val instanceof Boolean) {
-            return BigDecimal.valueOf(((Boolean) val).booleanValue() ? 1. : 0.);
+            return BigDecimal.valueOf(((Boolean) val) ? 1. : 0.);
         } else if (val instanceof String) {
             String string = (String) val;
             if ("".equals(string)) {
@@ -1326,7 +1273,7 @@ public class JexlArithmetic {
             }
             return roundBigDecimal(new BigDecimal(string, getMathContext()));
         } else if (val instanceof Character) {
-            int i = ((Character) val).charValue();
+            int i = ((Character) val);
             return new BigDecimal(i);
         }
         throw new ArithmeticException("BigDecimal coercion: "
@@ -1337,22 +1284,22 @@ public class JexlArithmetic {
      * Coerce to a primitive double.
      * <p>Double.NaN, null and empty string coerce to zero.</p>
      * <p>Boolean false is 0, true is 1.</p>
-     * @param val Object to be coerced.
+     * @param val value to coerce.
      * @return The double coerced value.
-     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
+     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible
      */
     public double toDouble(Object val) {
         if (val == null) {
             controlNullOperand();
             return 0;
         } else if (val instanceof Double) {
-            return ((Double) val).doubleValue();
+            return ((Double) val);
         } else if (val instanceof Number) {
             //The below construct is used rather than ((Number)val).doubleValue() to ensure
             //equality between comparing new Double( 6.4 / 3 ) and the jexl expression of 6.4 / 3
             return Double.parseDouble(String.valueOf(val));
         } else if (val instanceof Boolean) {
-            return ((Boolean) val).booleanValue() ? 1. : 0.;
+            return ((Boolean) val) ? 1. : 0.;
         } else if (val instanceof String) {
             String string = (String) val;
             if ("".equals(string)) {
@@ -1362,7 +1309,7 @@ public class JexlArithmetic {
                 return Double.parseDouble(string);
             }
         } else if (val instanceof Character) {
-            int i = ((Character) val).charValue();
+            int i = ((Character) val);
             return i;
         }
         throw new ArithmeticException("Double coercion: "
@@ -1373,9 +1320,9 @@ public class JexlArithmetic {
      * Coerce to a string.
      * <p>Double.NaN coerce to the empty string.</p>
      *
-     * @param val Object to be coerced.
+     * @param val value to coerce.
      * @return The String coerced value.
-     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
+     * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible
      */
     public String toString(Object val) {
         if (val == null) {
@@ -1383,7 +1330,7 @@ public class JexlArithmetic {
             return "";
         } else if (val instanceof Double) {
             Double dval = (Double) val;
-            if (Double.isNaN(dval.doubleValue())) {
+            if (Double.isNaN(dval)) {
                 return "";
             } else {
                 return dval.toString();
@@ -1392,4 +1339,68 @@ public class JexlArithmetic {
             return val.toString();
         }
     }
-}
\ No newline at end of file
+
+    /**
+     * Use or overload and() instead.
+     * @param lhs left hand side
+     * @param rhs right hand side
+     * @return lhs & rhs
+     * @see JexlArithmetic#and
+     * @deprecated
+     */
+    @Deprecated
+    public final Object bitwiseAnd(Object lhs, Object rhs) {
+        return and(lhs, rhs);
+    }
+    /**
+     * Use or overload or() instead.
+     * @param lhs left hand side
+     * @param rhs right hand side
+     * @return lhs | rhs
+     * @see JexlArithmetic#or
+     * @deprecated
+     */
+    @Deprecated
+    public final Object bitwiseOr(Object lhs, Object rhs) {
+        return or(lhs, rhs);
+    }
+
+    /**
+     * Use or overload xor() instead.
+     * @param lhs left hand side
+     * @param rhs right hand side
+     * @return lhs ^ rhs
+     * @see JexlArithmetic#xor
+     * @deprecated
+     */
+    @Deprecated
+    public final Object bitwiseXor(Object lhs, Object rhs) {
+        return xor(lhs, rhs);
+    }
+
+    /**
+     * Use or overload not() instead.
+     * @param arg argument
+     * @return !arg
+     * @see JexlArithmetic#not
+     * @deprecated
+     */
+    @Deprecated
+    public final Object logicalNot(Object arg) {
+        return not(arg);
+    }
+
+    /**
+     * Use or overload contains() instead.
+     * @param lhs left hand side
+     * @param rhs right hand side
+     * @return contains(rhs, lhs)
+     * @see JexlArithmetic#contains
+     * @deprecated
+     */
+    @Deprecated
+    public final Object matches(Object lhs, Object rhs) {
+        return contains(rhs, lhs);
+    }
+
+}

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java?rev=1692852&r1=1692851&r2=1692852&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java Mon Jul 27 10:02:49 2015
@@ -162,9 +162,9 @@ public class JexlException extends Runti
      */
     private static Throwable unwrap(Throwable xthrow) {
         if (xthrow instanceof InvocationTargetException) {
-            return ((InvocationTargetException) xthrow).getTargetException();
+            return ((InvocationTargetException) xthrow).getCause();
         } else if (xthrow instanceof UndeclaredThrowableException) {
-            return ((UndeclaredThrowableException) xthrow).getUndeclaredThrowable();
+            return ((UndeclaredThrowableException) xthrow).getCause();
         } else {
             return xthrow;
         }

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlOperator.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlOperator.java?rev=1692852&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlOperator.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlOperator.java Mon Jul 27 10:02:49 2015
@@ -0,0 +1,284 @@
+/*
+ * 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;
+
+/**
+ * The JEXL operators.
+ *
+ * These are the operators that are executed by JexlArithmetic methods.
+ * <p>
+ * Each of them  associates a symbol to a method signature.
+ * For instance, '+' is associated to 'T add(L x, R y)'.
+ * </p>
+ * <p>
+ * The default JexlArithmetic implements generic versions of these methods using Object as arguments.
+ * You can use your own derived JexlArithmetic that override and/or overload those operator methods; these methods
+ * must be public,
+ * must respect the return type when primitive
+ * and may be overloaded multiple times with different signatures.
+ * </p>
+ * @since 3.0
+ */
+public enum JexlOperator {
+    /**
+     * <strong>Syntax:</strong> <code>x + y</code>
+     * <br><strong>Method:</strong> <code>T add(L x, R y);</code>
+     * @see JexlArithmetic#add
+     */
+    ADD("+", "add", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x - y</code>
+     * <br><strong>Method:</strong> <code>T subtract(L x, R y);</code>
+     * @see JexlArithmetic#subtract
+     */
+    SUBTRACT("-", "subtract", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x * y</code>
+     * <br><strong>Method:</strong> <code>T multiply(L x, R y);</code>
+     * @see JexlArithmetic#multiply
+     */
+    MULTIPLY("*", "multiply", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x / y</code>
+     * <br><strong>Method:</strong> <code>T divide(L x, R y);</code>
+     * @see JexlArithmetic#divide
+     */
+    DIVIDE("/", "divide", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x % y</code>
+     * <br><strong>Method:</strong> <code>T mod(L x, R y);</code>
+     * @see JexlArithmetic#mod
+     */
+    MOD("%", "mod", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x & y</code>
+     * <br><strong>Method:</strong> <code>T and(L x, R y);</code>
+     * @see JexlArithmetic#and
+     */
+    AND("&", "and", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x | y</code>
+     * <br><strong>Method:</strong> <code>T or(L x, R y);</code>
+     * @see JexlArithmetic#or
+     */
+    OR("|", "or", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x ^ y</code>
+     * <br><strong>Method:</strong> <code>T xor(L x, R y);</code>
+     * @see JexlArithmetic#xor
+     */
+    XOR("^", "xor", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x == y</code>
+     * <br><strong>Method:</strong> <code>boolean equals(L x, R y);</code>
+     * @see JexlArithmetic#equals
+     */
+    EQ("==", "equals", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x < y</code>
+     * <br><strong>Method:</strong> <code>boolean lessThan(L x, R y);</code>
+     * @see JexlArithmetic#lessThan
+     */
+    LT("<", "lessThan", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x <= y</code>
+     * <br><strong>Method:</strong> <code>boolean lessThanOrEqual(L x, R y);</code>
+     * @see JexlArithmetic#lessThanOrEqual
+     */
+    LTE("<=", "lessThanOrEqual", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x > y</code>
+     * <br><strong>Method:</strong> <code>boolean greaterThan(L x, R y);</code>
+     * @see JexlArithmetic#greaterThan
+     */
+    GT(">", "greaterThan", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x >= y</code>
+     * <br><strong>Method:</strong> <code>boolean greaterThanOrEqual(L x, R y);</code>
+     * @see JexlArithmetic#greaterThanOrEqual
+     */
+    GTE(">=", "greaterThanOrEqual", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x =~ y</code>
+     * <br><strong>Method:</strong> <code>boolean contains(L x, R y);</code>
+     * @see JexlArithmetic#contains
+     */
+    CONTAINS("=~", "contains", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x =^ y</code>
+     * <br><strong>Method:</strong> <code>boolean startsWith(L x, R y);</code>
+     * @see JexlArithmetic#startsWith
+     */
+    STARTSWITH("=^", "startsWith", 2),
+    /**
+     * <strong>Syntax:</strong> <code>x =$ y</code>
+     * <br><strong>Method:</strong> <code>boolean endsWith(L x, R y);</code>
+     * @see JexlArithmetic#endsWith
+     */
+    ENDSWITH("=$", "endsWith", 2),
+    /**
+     * <strong>Syntax:</strong> <code>!x</code>
+     * <br><strong>Method:</strong> <code>T not(L x);</code>
+     * @see JexlArithmetic#not
+     */
+    NOT("!", "not", 1),
+    /**
+     * <strong>Syntax:</strong> <code>~x</code>
+     * <br><strong>Method:</strong> <code>T complement(L x);</code>
+     * @see JexlArithmetic#complement
+     */
+    COMPLEMENT("~", "complement", 1),
+    /**
+     * <strong>Syntax:</strong> <code>-x</code>
+     * <br><strong>Method:</strong> <code>T negate(L x);</code>
+     * @see JexlArithmetic#negate
+     */
+    NEGATE("-", "negate", 1),
+    /**
+     * <strong>Syntax:</strong> <code>empty x</code> or <code>empty(x)</code>
+     * <br><strong>Method:</strong> <code>boolean isEmpty(L x);</code>
+     * @see JexlArithmetic#isEmpty
+     */
+    EMPTY("empty", "empty", 1),
+    /**
+     * <strong>Syntax:</strong> <code>size x</code> or <code>size(x)</code>
+     * <br><strong>Method:</strong> <code>int size(L x);</code>
+     * @see JexlArithmetic#size
+     */
+    SIZE("size", "size", 1),
+    /**
+     * <strong>Syntax:</strong> <code>x += y</code>
+     * <br><strong>Method:</strong> <code>T selfAdd(L x, R y);</code>
+     */
+    SELF_ADD("+=", "selfAdd", ADD),
+    /**
+     * <strong>Syntax:</strong> <code>x -= y</code>
+     * <br><strong>Method:</strong> <code>T selfSubtract(L x, R y);</code>
+     */
+    SELF_SUBTRACT("-=", "selfSubtract", SUBTRACT),
+    /**
+     * <strong>Syntax:</strong> <code>x *= y</code>
+     * <br><strong>Method:</strong> <code>T selfMultiply(L x, R y);</code>
+     */
+    SELF_MULTIPLY("*=", "selfMultiply", MULTIPLY),
+    /**
+     * <strong>Syntax:</strong> <code>x /= y</code>
+     * <br><strong>Method:</strong> <code>T selfDivide(L x, R y);</code>
+     */
+    SELF_DIVIDE("/=", "selfDivide", DIVIDE),
+    /**
+     * <strong>Syntax:</strong> <code>x %= y</code>
+     * <br><strong>Method:</strong> <code>T selfMod(L x, R y);</code>
+     */
+    SELF_MOD("%=", "selfMod", MOD),
+    /**
+     * <strong>Syntax:</strong> <code>x &= y</code>
+     * <br><strong>Method:</strong> <code>T selfAnd(L x, R y);</code>
+     */
+    SELF_AND("&=", "selfAnd", AND),
+    /**
+     * <strong>Syntax:</strong> <code>x |= y</code>
+     * <br><strong>Method:</strong> <code>T selfOr(L x, R y);</code>
+     */
+    SELF_OR("|=", "selfOr", OR),
+    /**
+     * <strong>Syntax:</strong> <code>x ^= y</code>
+     * <br><strong>Method:</strong> <code>T selfXor(L x, R y);</code>
+     */
+    SELF_XOR("^=", "selfXor", XOR),
+    /**
+     * Marker for side effect.
+     * <br/>Returns this from 'self*' overload method to let the engine know the side effect has been performed and
+     * there is no need to assign the result.
+     */
+    ASSIGN("=", null, null);
+    /**
+     * The operator symbol.
+     */
+    private final String operator;
+    /**
+     * The associated operator method name.
+     */
+    private final String methodName;
+    /**
+     * The method arity (ie number of arguments).
+     */
+    private final int arity;
+    /**
+     * The base operator.
+     */
+    private final JexlOperator base;
+
+    /**
+     * Creates a base operator.
+     * @param o    the operator name
+     * @param m    the method name associated to this operator in a JexlArithmetic
+     * @param argc the number of parameters for the method
+     */
+    JexlOperator(String o, String m, int argc) {
+        this.operator = o;
+        this.methodName = m;
+        this.arity = argc;
+        this.base = null;
+    }
+
+    /**
+     * Creates a side-effect operator.
+     * @param o the operator name
+     * @param m the method name associated to this operator in a JexlArithmetic
+     * @param b the base operator, ie + for +=
+     */
+    JexlOperator(String o, String m, JexlOperator b) {
+        this.operator = o;
+        this.methodName = m;
+        this.arity = 2;
+        this.base = b;
+    }
+
+    /**
+     * Gets this operator symbol.
+     * @return the symbol
+     */
+    public final String getOperatorSymbol() {
+        return operator;
+    }
+
+    /**
+     * Gets this operator method name in a JexlArithmetic.
+     * @return the method name
+     */
+    public final String getMethodName() {
+        return methodName;
+    }
+
+    /**
+     * Gets this operator number of parameters.
+     * @return the method arity
+     */
+    public int getArity() {
+        return arity;
+    }
+
+    /**
+     * Gets the base operator.
+     * @return the base operator
+     */
+    public final JexlOperator getBaseOperator() {
+        return base;
+    }
+
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlOperator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java?rev=1692852&r1=1692851&r2=1692852&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java Mon Jul 27 10:02:49 2015
@@ -172,7 +172,8 @@ public abstract class JxltEngine {
          * <p>
          * In effect, this binds the result of the immediate sub-expressions evaluation in the
          * context, allowing to differ evaluation of the remaining (deferred) expression within another context.
-         * This only has an effect to nested and composite expressions that contain differed and immediate sub-expressions.
+         * This only has an effect to nested and composite expressions that contain differed and
+         * immediate sub-expressions.
          * </p>
          * <p>
          * If the underlying JEXL engine is silent, errors will be logged through its logger as warning.
@@ -307,6 +308,7 @@ public abstract class JxltEngine {
 
         /**
          * Gets the list of parameters expected by this template.
+         * @return the parameter names array
          */
         String[] getParameters();
     }

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=1692852&r1=1692851&r2=1692852&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 Mon Jul 27 10:02:49 2015
@@ -71,7 +71,15 @@ import org.apache.commons.jexl3.parser.A
 import org.apache.commons.jexl3.parser.ASTReferenceExpression;
 import org.apache.commons.jexl3.parser.ASTReturnStatement;
 import org.apache.commons.jexl3.parser.ASTSWNode;
+import org.apache.commons.jexl3.parser.ASTSetAddNode;
+import org.apache.commons.jexl3.parser.ASTSetAndNode;
+import org.apache.commons.jexl3.parser.ASTSetDivNode;
 import org.apache.commons.jexl3.parser.ASTSetLiteral;
+import org.apache.commons.jexl3.parser.ASTSetModNode;
+import org.apache.commons.jexl3.parser.ASTSetMultNode;
+import org.apache.commons.jexl3.parser.ASTSetOrNode;
+import org.apache.commons.jexl3.parser.ASTSetSubNode;
+import org.apache.commons.jexl3.parser.ASTSetXorNode;
 import org.apache.commons.jexl3.parser.ASTSizeFunction;
 import org.apache.commons.jexl3.parser.ASTSizeMethod;
 import org.apache.commons.jexl3.parser.ASTStringLiteral;
@@ -874,4 +882,44 @@ public final class Debugger extends Pars
         }
         return data;
     }
+
+    @Override
+    protected Object visit(ASTSetAddNode node, Object data) {
+        return infixChildren(node, " += ", false, data);
+    }
+
+    @Override
+    protected Object visit(ASTSetSubNode node, Object data) {
+        return infixChildren(node, " -= ", false, data);
+    }
+
+    @Override
+    protected Object visit(ASTSetMultNode node, Object data) {
+        return infixChildren(node, " *= ", false, data);
+    }
+
+    @Override
+    protected Object visit(ASTSetDivNode node, Object data) {
+        return infixChildren(node, " /= ", false, data);
+    }
+
+    @Override
+    protected Object visit(ASTSetModNode node, Object data) {
+        return infixChildren(node, " %= ", false, data);
+    }
+
+    @Override
+    protected Object visit(ASTSetAndNode node, Object data) {
+        return infixChildren(node, " &= ", false, data);
+    }
+
+    @Override
+    protected Object visit(ASTSetOrNode node, Object data) {
+        return infixChildren(node, " |= ", false, data);
+    }
+
+    @Override
+    protected Object visit(ASTSetXorNode node, Object data) {
+        return infixChildren(node, " ^= ", false, data);
+    }
 }
\ No newline at end of file

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=1692852&r1=1692851&r2=1692852&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 Mon Jul 27 10:02:49 2015
@@ -30,7 +30,6 @@ public abstract class IntegerRange imple
     /** The upper boundary. */
     protected final int max;
 
-
     /**
      * Creates a range, ascending or descending depending on boundaries order.
      * @param from the lower inclusive boundary
@@ -50,13 +49,8 @@ public abstract class IntegerRange imple
      * @param to  the higher inclusive boundary
      */
     public IntegerRange(int from, int to) {
-        if (from > to) {
-            max = from;
-            min = to;
-        } else {
-            min = from;
-            max = to;
-        }
+        min = from;
+        max = to;
     }
 
     /**
@@ -202,6 +196,11 @@ public abstract class IntegerRange imple
      * Ascending integer range.
      */
     public static class Ascending extends IntegerRange {
+        /**
+         * Constructor.
+         * @param from lower boundary
+         * @param to upper boundary
+         */
         protected Ascending(int from, int to) {
             super(from, to);
         }
@@ -216,6 +215,11 @@ public abstract class IntegerRange imple
      * Descending integer range.
      */
     public static class Descending extends IntegerRange {
+        /**
+         * Constructor.
+         * @param from upper boundary
+         * @param to lower boundary
+         */
         protected Descending(int from, int to) {
             super(from, to);
         }