Class JexlArithmetic

  • Direct Known Subclasses:
    JexlThreadedArithmetic

    public class JexlArithmetic
    extends java.lang.Object
    Perform arithmetic.

    All arithmetic operators (+, - , *, /, %) follow the same rules regarding their arguments.

    1. If both are null, result is 0
    2. If either is a BigDecimal, coerce both to BigDecimal and and perform operation
    3. If either is a floating point number, coerce both to Double and perform operation
    4. If both are BigInteger, treat as BigInteger and perform operation
    5. Else treat as BigInteger, perform operation and attempt to narrow result:
      1. if both arguments can be narrowed to Integer, narrow result to Integer
      2. if both arguments can be narrowed to Long, narrow result to Long
      3. Else return result as BigInteger

    Note that the only exception throw by JexlArithmetic is ArithmeticException.
    Since:
    2.0
    • Field Summary

      Fields 
      Modifier and Type Field Description
      protected static java.math.BigDecimal BIGD_DOUBLE_MAX_VALUE
      Double.MAX_VALUE as BigDecimal.
      protected static java.math.BigDecimal BIGD_DOUBLE_MIN_VALUE
      Double.MIN_VALUE as BigDecimal.
      protected static int BIGD_SCALE
      Default BigDecimal scale.
      protected static java.math.BigInteger BIGI_LONG_MAX_VALUE
      Long.MAX_VALUE as BigInteger.
      protected static java.math.BigInteger BIGI_LONG_MIN_VALUE
      Long.MIN_VALUE as BigInteger.
      protected java.math.MathContext mathContext
      The big decimal math context.
      protected int mathScale
      The big decimal scale.
    • Constructor Summary

      Constructors 
      Constructor Description
      JexlArithmetic​(boolean lenient)
      Creates a JexlArithmetic.
      JexlArithmetic​(boolean lenient, java.math.MathContext bigdContext, int bigdScale)
      Creates a JexlArithmetic.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      java.lang.Object add​(java.lang.Object left, java.lang.Object right)
      Add two values together.
      java.lang.Object bitwiseAnd​(java.lang.Object left, java.lang.Object right)
      Performs a bitwise and.
      java.lang.Object bitwiseComplement​(java.lang.Object val)
      Performs a bitwise complement.
      java.lang.Object bitwiseOr​(java.lang.Object left, java.lang.Object right)
      Performs a bitwise or.
      java.lang.Object bitwiseXor​(java.lang.Object left, java.lang.Object right)
      Performs a bitwise xor.
      protected int compare​(java.lang.Object left, java.lang.Object right, java.lang.String operator)
      Performs a comparison.
      protected java.lang.Object controlNullNullOperands()
      The result of +,/,-,*,% when both operands are null.
      protected void controlNullOperand()
      Throw a NPE if arithmetic is strict.
      java.lang.Object divide​(java.lang.Object left, java.lang.Object right)
      Divide the left value by the right.
      boolean equals​(java.lang.Object left, java.lang.Object right)
      Test if left and right are equal.
      java.math.MathContext getMathContext()
      The MathContext instance used for +,-,/,*,% operations on big decimals.
      int getMathScale()
      The BigDecimal scale used for comparison and coercion operations.
      boolean greaterThan​(java.lang.Object left, java.lang.Object right)
      Test if left > right.
      boolean greaterThanOrEqual​(java.lang.Object left, java.lang.Object right)
      Test if left >= right.
      protected boolean isFloatingPoint​(java.lang.Object o)
      Is Object a floating point number.
      protected boolean isFloatingPointNumber​(java.lang.Object val)
      Test if the passed value is a floating point number, i.e.
      protected boolean isFloatingPointType​(java.lang.Object left, java.lang.Object right)
      Test if either left or right are either a Float or Double.
      boolean isLenient()
      Checks whether this JexlArithmetic instance triggers errors during evaluation when null is used as an operand.
      protected boolean isNumberable​(java.lang.Object o)
      Is Object a whole number.
      boolean lessThan​(java.lang.Object left, java.lang.Object right)
      Test if left < right.
      boolean lessThanOrEqual​(java.lang.Object left, java.lang.Object right)
      Test if left <= right.
      boolean matches​(java.lang.Object left, java.lang.Object right)
      Test if left regexp matches right.
      java.lang.Object mod​(java.lang.Object left, java.lang.Object right)
      left value mod right.
      java.lang.Object multiply​(java.lang.Object left, java.lang.Object right)
      Multiply the left value by the right.
      java.lang.Number narrow​(java.lang.Number original)
      Given a Number, return back the value using the smallest type the result will fit into.
      protected boolean narrowAccept​(java.lang.Class<?> narrow, java.lang.Class<?> source)
      Whether we consider the narrow class as a potential candidate for narrowing the source.
      protected boolean narrowArguments​(java.lang.Object[] args)
      Replace all numbers in an arguments array with the smallest type that will fit.
      protected java.lang.Object narrowArrayType​(java.lang.Object[] untyped)
      Given an array of objects, attempt to type it more strictly.
      protected java.lang.Number narrowBigDecimal​(java.lang.Object lhs, java.lang.Object rhs, java.math.BigDecimal bigd)
      Given a BigDecimal, attempt to narrow it to an Integer or Long if it fits if one of the arguments is a numberable.
      protected java.lang.Number narrowBigInteger​(java.lang.Object lhs, java.lang.Object rhs, java.math.BigInteger bigi)
      Given a BigInteger, narrow it to an Integer or Long if it fits and the arguments class allow it.
      protected java.lang.Number narrowNumber​(java.lang.Number original, java.lang.Class<?> narrow)
      Given a Number, return back the value attempting to narrow it to a target class.
      java.lang.Object negate​(java.lang.Object val)
      Negates a value (unary minus for numbers).
      java.math.BigDecimal roundBigDecimal​(java.math.BigDecimal number)
      Ensure a big decimal is rounded by this arithmetic scale and rounding mode.
      java.lang.Object subtract​(java.lang.Object left, java.lang.Object right)
      Subtract the right value from the left.
      java.math.BigDecimal toBigDecimal​(java.lang.Object val)
      Get a BigDecimal from the object passed.
      java.math.BigInteger toBigInteger​(java.lang.Object val)
      Get a BigInteger from the object passed.
      boolean toBoolean​(java.lang.Object val)
      Coerce to a boolean (not a java.lang.Boolean).
      double toDouble​(java.lang.Object val)
      Coerce to a double.
      int toInteger​(java.lang.Object val)
      Coerce to a int.
      long toLong​(java.lang.Object val)
      Coerce to a long (not a java.lang.Long).
      java.lang.String toString​(java.lang.Object val)
      Coerce to a string.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • BIGD_DOUBLE_MAX_VALUE

        protected static final java.math.BigDecimal BIGD_DOUBLE_MAX_VALUE
        Double.MAX_VALUE as BigDecimal.
      • BIGD_DOUBLE_MIN_VALUE

        protected static final java.math.BigDecimal BIGD_DOUBLE_MIN_VALUE
        Double.MIN_VALUE as BigDecimal.
      • BIGI_LONG_MAX_VALUE

        protected static final java.math.BigInteger BIGI_LONG_MAX_VALUE
        Long.MAX_VALUE as BigInteger.
      • BIGI_LONG_MIN_VALUE

        protected static final java.math.BigInteger BIGI_LONG_MIN_VALUE
        Long.MIN_VALUE as BigInteger.
      • BIGD_SCALE

        protected static final int BIGD_SCALE
        Default BigDecimal scale.
        Since:
        2.1
        See Also:
        Constant Field Values
      • mathContext

        protected final java.math.MathContext mathContext
        The big decimal math context.
        Since:
        2.1
      • mathScale

        protected final int mathScale
        The big decimal scale.
        Since:
        2.1
    • Constructor Detail

      • JexlArithmetic

        public JexlArithmetic​(boolean lenient)
        Creates a JexlArithmetic.
        Parameters:
        lenient - whether this arithmetic is lenient or strict
      • JexlArithmetic

        public JexlArithmetic​(boolean lenient,
                              java.math.MathContext bigdContext,
                              int bigdScale)
        Creates a JexlArithmetic.
        Parameters:
        lenient - whether this arithmetic is lenient or strict
        bigdContext - the math context instance to use for +,-,/,*,% operations on big decimals.
        bigdScale - the scale used for big decimals.
        Since:
        2.1
    • Method Detail

      • isLenient

        public boolean isLenient()
        Checks whether this JexlArithmetic instance triggers errors during evaluation when null is used as an operand.
        Returns:
        true if lenient, false if strict
      • getMathContext

        public java.math.MathContext getMathContext()
        The MathContext instance used for +,-,/,*,% operations on big decimals.
        Returns:
        the math context
        Since:
        2.1
      • getMathScale

        public int getMathScale()
        The BigDecimal scale used for comparison and coercion operations.
        Returns:
        the scale
        Since:
        2.1
      • roundBigDecimal

        public java.math.BigDecimal roundBigDecimal​(java.math.BigDecimal number)
        Ensure a big decimal is rounded by this arithmetic scale and rounding mode.
        Parameters:
        number - the big decimal to round
        Returns:
        the rounded big decimal
        Since:
        2.1
      • controlNullNullOperands

        protected java.lang.Object controlNullNullOperands()
        The result of +,/,-,*,% when both operands are null.
        Returns:
        Integer(0) if lenient
        Throws:
        java.lang.ArithmeticException - if strict
      • controlNullOperand

        protected void controlNullOperand()
        Throw a NPE if arithmetic is strict.
        Throws:
        java.lang.ArithmeticException - if strict
      • isFloatingPointType

        protected boolean isFloatingPointType​(java.lang.Object left,
                                              java.lang.Object right)
        Test if either left or right are either a Float or Double.
        Parameters:
        left - one object to test
        right - the other
        Returns:
        the result of the test.
      • isFloatingPointNumber

        protected boolean isFloatingPointNumber​(java.lang.Object val)
        Test if the passed value is a floating point number, i.e. a float, double or string with ( "." | "E" | "e").
        Parameters:
        val - the object to be tested
        Returns:
        true if it is, false otherwise.
      • isFloatingPoint

        protected boolean isFloatingPoint​(java.lang.Object o)
        Is Object a floating point number.
        Parameters:
        o - Object to be analyzed.
        Returns:
        true if it is a Float or a Double.
      • isNumberable

        protected boolean isNumberable​(java.lang.Object o)
        Is Object a whole number.
        Parameters:
        o - Object to be analyzed.
        Returns:
        true if Integer, Long, Byte, Short or Character.
      • narrowBigInteger

        protected java.lang.Number narrowBigInteger​(java.lang.Object lhs,
                                                    java.lang.Object rhs,
                                                    java.math.BigInteger bigi)
        Given a BigInteger, narrow it to an Integer or Long if it fits and the arguments class allow it.

        The rules are: if either arguments is a BigInteger, no narrowing will occur if either arguments is a Long, no narrowing to Integer will occur

        Parameters:
        lhs - the left hand side operand that lead to the bigi result
        rhs - the right hand side operand that lead to the bigi result
        bigi - the BigInteger to narrow
        Returns:
        an Integer or Long if narrowing is possible, the original BigInteger otherwise
      • narrowBigDecimal

        protected java.lang.Number narrowBigDecimal​(java.lang.Object lhs,
                                                    java.lang.Object rhs,
                                                    java.math.BigDecimal bigd)
        Given a BigDecimal, attempt to narrow it to an Integer or Long if it fits if one of the arguments is a numberable.
        Parameters:
        lhs - the left hand side operand that lead to the bigd result
        rhs - the right hand side operand that lead to the bigd result
        bigd - the BigDecimal to narrow
        Returns:
        an Integer or Long if narrowing is possible, the original BigInteger otherwise
        Since:
        2.1
      • narrowArrayType

        protected java.lang.Object narrowArrayType​(java.lang.Object[] untyped)
        Given an array of objects, attempt to type it more strictly.
        • If all objects are of the same type, the array returned will be an array of that same type
        • If all objects are Numbers, the array returned will be an array of Numbers
        • If all objects are convertible to a primitive type, the array returned will be an array of the primitive type
        Parameters:
        untyped - an untyped array
        Returns:
        the original array if the attempt to strictly type the array fails, a typed array otherwise
      • narrowArguments

        protected boolean narrowArguments​(java.lang.Object[] args)
        Replace all numbers in an arguments array with the smallest type that will fit.
        Parameters:
        args - the argument array
        Returns:
        true if some arguments were narrowed and args array is modified, false if no narrowing occured and args array has not been modified
      • add

        public java.lang.Object add​(java.lang.Object left,
                                    java.lang.Object right)
        Add two values together.

        If any numeric add fails on coercion to the appropriate type, treat as Strings and do concatenation.

        Parameters:
        left - first value
        right - second value
        Returns:
        left + right.
      • divide

        public java.lang.Object divide​(java.lang.Object left,
                                       java.lang.Object right)
        Divide the left value by the right.
        Parameters:
        left - first value
        right - second value
        Returns:
        left / right
        Throws:
        java.lang.ArithmeticException - if right == 0
      • mod

        public java.lang.Object mod​(java.lang.Object left,
                                    java.lang.Object right)
        left value mod right.
        Parameters:
        left - first value
        right - second value
        Returns:
        left mod right
        Throws:
        java.lang.ArithmeticException - if right == 0.0
      • multiply

        public java.lang.Object multiply​(java.lang.Object left,
                                         java.lang.Object right)
        Multiply the left value by the right.
        Parameters:
        left - first value
        right - second value
        Returns:
        left * right.
      • subtract

        public java.lang.Object subtract​(java.lang.Object left,
                                         java.lang.Object right)
        Subtract the right value from the left.
        Parameters:
        left - first value
        right - second value
        Returns:
        left - right.
      • negate

        public java.lang.Object negate​(java.lang.Object val)
        Negates a value (unary minus for numbers).
        Parameters:
        val - the value to negate
        Returns:
        the negated value
        Since:
        2.1
      • matches

        public boolean matches​(java.lang.Object left,
                               java.lang.Object right)
        Test if left regexp matches right.
        Parameters:
        left - first value
        right - second value
        Returns:
        test result.
        Since:
        2.1
      • bitwiseAnd

        public java.lang.Object bitwiseAnd​(java.lang.Object left,
                                           java.lang.Object right)
        Performs a bitwise and.
        Parameters:
        left - the left operand
        right - the right operator
        Returns:
        left & right
        Since:
        2.1
      • bitwiseOr

        public java.lang.Object bitwiseOr​(java.lang.Object left,
                                          java.lang.Object right)
        Performs a bitwise or.
        Parameters:
        left - the left operand
        right - the right operator
        Returns:
        left | right
        Since:
        2.1
      • bitwiseXor

        public java.lang.Object bitwiseXor​(java.lang.Object left,
                                           java.lang.Object right)
        Performs a bitwise xor.
        Parameters:
        left - the left operand
        right - the right operator
        Returns:
        left right
        Since:
        2.1
      • bitwiseComplement

        public java.lang.Object bitwiseComplement​(java.lang.Object val)
        Performs a bitwise complement.
        Parameters:
        val - the operand
        Returns:
        ~val
        Since:
        2.1
      • compare

        protected int compare​(java.lang.Object left,
                              java.lang.Object right,
                              java.lang.String operator)
        Performs a comparison.
        Parameters:
        left - the left operand
        right - the right operator
        operator - the operator
        Returns:
        -1 if left < right; +1 if left > > right; 0 if left == right
        Throws:
        java.lang.ArithmeticException - if either left or right is null
        Since:
        2.1
      • equals

        public boolean equals​(java.lang.Object left,
                              java.lang.Object right)
        Test if left and right are equal.
        Parameters:
        left - first value
        right - second value
        Returns:
        test result.
      • lessThan

        public boolean lessThan​(java.lang.Object left,
                                java.lang.Object right)
        Test if left < right.
        Parameters:
        left - first value
        right - second value
        Returns:
        test result.
      • greaterThan

        public boolean greaterThan​(java.lang.Object left,
                                   java.lang.Object right)
        Test if left > right.
        Parameters:
        left - first value
        right - second value
        Returns:
        test result.
      • lessThanOrEqual

        public boolean lessThanOrEqual​(java.lang.Object left,
                                       java.lang.Object right)
        Test if left <= right.
        Parameters:
        left - first value
        right - second value
        Returns:
        test result.
      • greaterThanOrEqual

        public boolean greaterThanOrEqual​(java.lang.Object left,
                                          java.lang.Object right)
        Test if left >= right.
        Parameters:
        left - first value
        right - second value
        Returns:
        test result.
      • toBoolean

        public boolean toBoolean​(java.lang.Object val)
        Coerce to a boolean (not a java.lang.Boolean).
        Parameters:
        val - Object to be coerced.
        Returns:
        The boolean coerced value, or false if none possible.
      • toInteger

        public int toInteger​(java.lang.Object val)
        Coerce to a int.
        Parameters:
        val - Object to be coerced.
        Returns:
        The int coerced value.
      • toLong

        public long toLong​(java.lang.Object val)
        Coerce to a long (not a java.lang.Long).
        Parameters:
        val - Object to be coerced.
        Returns:
        The long coerced value.
      • toBigInteger

        public java.math.BigInteger toBigInteger​(java.lang.Object val)
        Get a BigInteger from the object passed. Null and empty string maps to zero.
        Parameters:
        val - the object to be coerced.
        Returns:
        a BigDecimal.
        Throws:
        java.lang.NullPointerException - if val is null and mode is strict.
      • toBigDecimal

        public java.math.BigDecimal toBigDecimal​(java.lang.Object val)
        Get a BigDecimal from the object passed. Null and empty string maps to zero.
        Parameters:
        val - the object to be coerced.
        Returns:
        a BigDecimal.
        Throws:
        java.lang.NullPointerException - if val is null and mode is strict.
      • toDouble

        public double toDouble​(java.lang.Object val)
        Coerce to a double.
        Parameters:
        val - Object to be coerced.
        Returns:
        The double coerced value.
        Throws:
        java.lang.NullPointerException - if val is null and mode is strict.
      • toString

        public java.lang.String toString​(java.lang.Object val)
        Coerce to a string.
        Parameters:
        val - Object to be coerced.
        Returns:
        The String coerced value.
        Throws:
        java.lang.NullPointerException - if val is null and mode is strict.
      • narrow

        public java.lang.Number narrow​(java.lang.Number original)
        Given a Number, return back the value using the smallest type the result will fit into. This works hand in hand with parameter 'widening' in java method calls, e.g. a call to substring(int,int) with an int and a long will fail, but a call to substring(int,int) with an int and a short will succeed.
        Parameters:
        original - the original number.
        Returns:
        a value of the smallest type the original number will fit into.
      • narrowAccept

        protected boolean narrowAccept​(java.lang.Class<?> narrow,
                                       java.lang.Class<?> source)
        Whether we consider the narrow class as a potential candidate for narrowing the source.
        Parameters:
        narrow - the target narrow class
        source - the orginal source class
        Returns:
        true if attempt to narrow source to target is accepted
        Since:
        2.1
      • narrowNumber

        protected java.lang.Number narrowNumber​(java.lang.Number original,
                                                java.lang.Class<?> narrow)
        Given a Number, return back the value attempting to narrow it to a target class.
        Parameters:
        original - the original number
        narrow - the attempted target class
        Returns:
        the narrowed number or the source if no narrowing was possible
        Since:
        2.1