Package org.apache.commons.jexl3

# Class JexlArithmetic

java.lang.Object
org.apache.commons.jexl3.JexlArithmetic

public class JexlArithmetic extends Object
Perform arithmetic, implements JexlOperator methods.

This is the class to derive to implement new operator behaviors.

The 5 base arithmetic operators (+, - , *, /, %) follow the same evaluation rules regarding their arguments.

1. If both are null, result is 0 if arithmetic (or operator) is non-strict, ArithmeticException is thrown otherwise
2. If both arguments are numberable - any kind of integer including boolean -, coerce both to Long and coerce result to the most precise argument class (`boolean < byte < short < int < long`); if long operation would cause overflow, return a BigInteger
3. If either argument is a BigDecimal, coerce both to BigDecimal, operator returns BigDecimal
4. If either argument is a floating point number, coerce both to Double, operator returns Double
5. Else treat as BigInteger, perform operation and narrow result to the most precise argument class

Note that the only exception thrown by JexlArithmetic is and must be ArithmeticException.

Since:
  2.0
See Also:
  - `JexlOperator`

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static interface`
  `JexlArithmetic.ArrayBuilder`
  Helper interface used when creating an array literal.
  `static class`
  `JexlArithmetic.CoercionException`
  Marker class for coercion operand exceptions.
  `static interface`
  `JexlArithmetic.MapBuilder`
  Helper interface used when creating a map literal.
  `static class`
  `JexlArithmetic.NullOperand`
  Marker class for null operand exceptions.
  `static interface`
  `JexlArithmetic.SetBuilder`
  Helper interface used when creating a set literal.
  `static interface`
  `JexlArithmetic.Uberspect`
  The interface that uberspects JexlArithmetic classes.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected static final BigDecimal`
  `BIGD_DOUBLE_MAX_VALUE`
  Double.MAX_VALUE as BigDecimal.
  `protected static final BigDecimal`
  `BIGD_DOUBLE_MIN_VALUE`
  -Double.MAX_VALUE as BigDecimal.
  `protected static final int`
  `BIGD_SCALE`
  Default BigDecimal scale.
  `protected static final BigInteger`
  `BIGI_LONG_MAX_VALUE`
  Long.MAX_VALUE as BigInteger.
  `protected static final BigInteger`
  `BIGI_LONG_MIN_VALUE`
  Long.MIN_VALUE as BigInteger.
  `static final Pattern`
  `FLOAT_PATTERN`
  The float regular expression pattern.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `JexlArithmetic(boolean astrict)`
  Creates a JexlArithmetic.
  `JexlArithmetic(boolean astrict, MathContext bigdContext, int bigdScale)`
  Creates a JexlArithmetic.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `Object`
  `add(Object left, Object right)`
  Add two values together.
  `Object`
  `and(Object left, Object right)`
  Performs a bitwise and.
  `JexlArithmetic.ArrayBuilder`
  `arrayBuilder(int size)`
  Deprecated.
  since 3.3.1
  `JexlArithmetic.ArrayBuilder`
  `arrayBuilder(int size, boolean extended)`
  Called by the interpreter when evaluating a literal array.
  `protected Number`
  `asLongNumber(boolean strict, Object value)`
  Checks if value class is a number that can be represented exactly in a long.
  `protected Number`
  `asLongNumber(Object value)`
  Checks if value class is a number that can be represented exactly in a long.
  `final Object`
  `bitwiseAnd(Object lhs, Object rhs)`
  Deprecated.
  3.0
  `final Object`
  `bitwiseOr(Object lhs, Object rhs)`
  Deprecated.
  3.0
  `final Object`
  `bitwiseXor(Object lhs, Object rhs)`
  Deprecated.
  3.0
  `protected Boolean`
  `collectionContains(Object collection, Object value)`
  Checks whether a potential collection contains another.
  `protected int`
  `compare(Object left, Object right, String symbol)`
  Deprecated.
  3.3
  `protected int`
  `compare(Object left, Object right, JexlOperator operator)`
  Performs a comparison.
  `Object`
  `complement(Object val)`
  Performs a bitwise complement.
  `Boolean`
  `contains(Object container, Object value)`
  Test if left contains right (right matches/in left).
  `protected Object`
  `controlNullNullOperands()`
  Deprecated.
  3.3
  `protected Object`
  `controlNullNullOperands(JexlOperator operator)`
  The result of +,/,-,*,% when both operands are null.
  `protected void`
  `controlNullOperand()`
  Deprecated.
  3.3
  `protected <T> T`
  `controlNullOperand(boolean strictCast, T defaultValue)`
  Throws an NullOperand exception if arithmetic is strict-cast.
  `Object`
  `controlReturn(Object returned)`
  The last method called before returning a result from a script execution.
  `Iterable<?>`
  `createRange(Object from, Object to)`
  Creates a literal range.
  `protected JexlArithmetic`
  `createWithOptions(boolean astrict, MathContext bigdContext, int bigdScale)`
  Creates a JexlArithmetic instance.
  `Object`
  `decrement(Object val)`
  Decrements argument by 1.
  `Object`
  `divide(Object left, Object right)`
  Divide the left value by the right.
  `Boolean`
  `empty(Object object)`
  Check for emptiness of various types: Number, Collection, Array, Map, String.
  `Boolean`
  `endsWith(Object left, Object right)`
  Test if left ends with right.
  `boolean`
  `equals(Object left, Object right)`
  Test if left and right are equal.
  `Object`
  `evaluate(org.apache.commons.logging.Log logger, Supplier<Object> arg)`
  Evaluates a supplier argument, eventually catching and logging any JexlException.
  `MathContext`
  `getMathContext()`
  The MathContext instance used for +,-,/,*,% operations on big decimals.
  `int`
  `getMathScale()`
  The BigDecimal scale used for comparison and coercion operations.
  `boolean`
  `greaterThan(Object left, Object right)`
  Test if left > right.
  `boolean`
  `greaterThanOrEqual(Object left, Object right)`
  Test if left >= right.
  `Object`
  `increment(Object val)`
  Increments argument by 1.
  `protected Object`
  `increment(Object val, int incr)`
  Add value to number argument.
  `Boolean`
  `isEmpty(Object object)`
  Check for emptiness of various types: Number, Collection, Array, Map, String.
  `Boolean`
  `isEmpty(Object object, Boolean def)`
  Check for emptiness of various types: Number, Collection, Array, Map, String.
  `protected boolean`
  `isFloatingPoint(Object o)`
  Is Object a floating point number.
  `protected boolean`
  `isFloatingPointNumber(Object val)`
  Test if the passed value is a floating point number, i.e. a float, double or string with ( "." | "E" | "e").
  `protected static boolean`
  `isMultiplyExact(long x, long y, long r)`
  Checks if the product of the arguments overflows a `long`.
  `boolean`
  `isNegateStable()`
  Tests whether negate called with a given argument will always return the same result.
  `protected boolean`
  `isNullOperand(Object value)`
  Checks if an operand is considered null.
  `protected boolean`
  `isNumberable(Object o)`
  Is Object a whole number.
  `boolean`
  `isPositivizeStable()`
  Tests whether positivize called with a given argument will always return the same result.
  `boolean`
  `isStrict()`
  Checks whether this JexlArithmetic instance strictly considers null as an error when used as operand unexpectedly.
  `boolean`
  `isStrict(JexlOperator operator)`
  Tests whether this arithmetic considers a given operator as strict or null-safe.
  `boolean`
  `lessThan(Object left, Object right)`
  Tests if left < right.
  `boolean`
  `lessThanOrEqual(Object left, Object right)`
  Tests if left <= right.
  `final Object`
  `logicalNot(Object arg)`
  Deprecated.
  3.0
  `JexlArithmetic.MapBuilder`
  `mapBuilder(int size)`
  Deprecated.
  3.3
  `JexlArithmetic.MapBuilder`
  `mapBuilder(int size, boolean extended)`
  Called by the interpreter when evaluating a literal map.
  `final Object`
  `matches(Object lhs, Object rhs)`
  Deprecated.
  3.0
  `Object`
  `mod(Object left, Object right)`
  left value modulo right.
  `Object`
  `multiply(Object left, Object right)`
  Multiply the left value by the right.
  `Number`
  `narrow(Number original)`
  Given a Number, return the value using the smallest type the result will fit into.
  `protected boolean`
  `narrowAccept(Class<?> narrow, Class<?> source)`
  Tests whether we consider the narrow class as a potential candidate for narrowing the source.
  `boolean`
  `narrowArguments(Object[] args)`
  Replace all numbers in an arguments array with the smallest type that will fit.
  `protected Number`
  `narrowBigDecimal(Object lhs, Object rhs, BigDecimal big)`
  Given a BigDecimal, attempt to narrow it to an Integer or Long if it fits and one of the arguments is numberable.
  `protected Number`
  `narrowBigInteger(Object lhs, Object rhs, BigInteger big)`
  Given a BigInteger, narrow it to an Integer or Long if it fits and the arguments class allow it.
  `protected Number`
  `narrowLong(Object lhs, Object rhs, long r)`
  Given a long, attempt to narrow it to an int.
  `Number`
  `narrowNumber(Number original, Class<?> narrow)`
  Given a Number, return the value attempting to narrow it to a target class.
  `protected <X extends Number>
  Number`
  `narrowToLong(Object lhs, Object rhs, X big, ToLongFunction<X> toLongFunction)`
  Given a generic number, attempt to narrow it to an Integer or Long if it fits and one of the arguments is numberable.
  `Object`
  `negate(Object val)`
  Negates a value (unary minus for numbers).
  `Object`
  `not(Object val)`
  Performs a logical not.
  `JexlArithmetic`
  `options(JexlContext context)`
  Apply options to this arithmetic which eventually may create another instance.
  `JexlArithmetic`
  `options(JexlEngine.Options options)`
  Deprecated.
  3.2
  `JexlArithmetic`
  `options(JexlOptions options)`
  Apply options to this arithmetic which eventually may create another instance.
  `Object`
  `or(Object left, Object right)`
  Performs a bitwise or.
  `static Integer`
  `parseIdentifier(Object id)`
  Parse an identifier which must be of the form: 0|([1-9][0-9]*)
  `Object`
  `positivize(Object val)`
  Positivize value (unary plus for numbers).
  `protected BigDecimal`
  `roundBigDecimal(BigDecimal number)`
  Ensure a big decimal is rounded by this arithmetic scale and rounding mode.
  `JexlArithmetic.SetBuilder`
  `setBuilder(int size)`
  Deprecated.
  since 3.3.1
  `JexlArithmetic.SetBuilder`
  `setBuilder(int size, boolean extended)`
  Called by the interpreter when evaluating a literal set.
  `Object`
  `shiftLeft(Object left, Object right)`
  Shifts a bit pattern to the right.
  `Object`
  `shiftRight(Object left, Object right)`
  Shifts a bit pattern to the right.
  `Object`
  `shiftRightUnsigned(Object left, Object right)`
  Shifts a bit pattern to the right unsigned.
  `Integer`
  `size(Object object)`
  Calculate the `size` of various types: Collection, Array, Map, String.
  `Integer`
  `size(Object object, Integer def)`
  Calculate the `size` of various types: Collection, Array, Map, String.
  `Boolean`
  `startsWith(Object left, Object right)`
  Test if left starts with right.
  `boolean`
  `strictEquals(Object left, Object right)`
  Test if left and right are strictly equal.
  `Object`
  `subtract(Object left, Object right)`
  Subtract the right value from the left.
  `boolean`
  `testPredicate(Object object)`
  Test if a condition is true or false.
  `protected BigDecimal`
  `toBigDecimal(boolean strict, Object val)`
  Coerce to a BigDecimal.
  `BigDecimal`
  `toBigDecimal(Object val)`
  Coerce to a BigDecimal.
  `protected BigInteger`
  `toBigInteger(boolean strict, Object val)`
  Coerce to a BigInteger.
  `BigInteger`
  `toBigInteger(Object val)`
  Coerce to a BigInteger.
  `protected boolean`
  `toBoolean(boolean strict, Object val)`
  Coerce to a primitive boolean.
  `boolean`
  `toBoolean(Object val)`
  Coerce to a primitive boolean.
  `protected double`
  `toDouble(boolean strict, Object val)`
  Coerce to a primitive double.
  `double`
  `toDouble(Object val)`
  Coerce to a primitive double.
  `protected int`
  `toInteger(boolean strict, Object val)`
  Coerce to a primitive int.
  `int`
  `toInteger(Object val)`
  Coerce to a primitive int.
  `protected long`
  `toLong(boolean strict, Object val)`
  Coerce to a primitive long.
  `long`
  `toLong(Object val)`
  Coerce to a primitive long.
  `protected String`
  `toString(boolean strict, Object val)`
  Coerce to a string.
  `String`
  `toString(Object val)`
  Coerce to a string.
  `Object`
  `xor(Object left, Object right)`
  Performs a bitwise xor.

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### BIGD_DOUBLE_MAX_VALUE

    protected static final BigDecimal BIGD_DOUBLE_MAX_VALUE
    Double.MAX_VALUE as BigDecimal.

  - ### BIGD_DOUBLE_MIN_VALUE

    protected static final BigDecimal BIGD_DOUBLE_MIN_VALUE
    -Double.MAX_VALUE as BigDecimal.

  - ### BIGI_LONG_MAX_VALUE

    protected static final BigInteger BIGI_LONG_MAX_VALUE
    Long.MAX_VALUE as BigInteger.

  - ### BIGI_LONG_MIN_VALUE

    protected static final BigInteger BIGI_LONG_MIN_VALUE
    Long.MIN_VALUE as BigInteger.

  - ### BIGD_SCALE

    protected static final int BIGD_SCALE
    Default BigDecimal scale.
    See Also:
      - Constant Field Values

  - ### FLOAT_PATTERN

    public static final Pattern FLOAT_PATTERN
    The float regular expression pattern.

    The decimal and exponent parts are optional and captured allowing to determine if the number is a real by checking whether one of these 2 capturing groups is not empty.

- ## Constructor Details

  - ### JexlArithmetic

    public JexlArithmetic(boolean astrict)
    Creates a JexlArithmetic.

    If you derive your own arithmetic, implement the other constructor that may be needed when dealing with options.

    Parameters:
      `astrict` - whether this arithmetic is strict or lenient

  - ### JexlArithmetic

    public JexlArithmetic(boolean astrict, MathContext bigdContext, int bigdScale)
    Creates a JexlArithmetic.

    The constructor to define in derived classes.

    Parameters:
      `astrict` - 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.

- ## Method Details

  - ### isMultiplyExact

    protected static boolean isMultiplyExact(long x, long y, long r)
    Checks if the product of the arguments overflows a `long`.

    see java8 Math.multiplyExact

    Parameters:
      `x` - the first value
      `y` - the second value
      `r` - the product
    Returns:
      true if product fits a long, false if it overflows

  - ### add

    public Object add(Object left, 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` - left argument
      `right` - right argument
    Returns:
      left + right.

  - ### and

    public Object and(Object left, Object right)
    Performs a bitwise and.
    Parameters:
      `left` - the left operand
      `right` - the right operator
    Returns:
      left & right

  - ### arrayBuilder

    @Deprecated public JexlArithmetic.ArrayBuilder arrayBuilder(int size)
    Deprecated.
    since 3.3.1
    Creates an array builder.
    Parameters:
      `size` - the number of elements in the array
    Returns:
      an array builder instance

  - ### arrayBuilder

    public JexlArithmetic.ArrayBuilder arrayBuilder(int size, boolean extended)
    Called by the interpreter when evaluating a literal array.
    Parameters:
      `size` - the number of elements in the array
      `extended` - whether the map is extended or not
    Returns:
      the array builder

  - ### asLongNumber

    protected Number asLongNumber(boolean strict, Object value)
    Checks if value class is a number that can be represented exactly in a long.

    For convenience, booleans are converted as 1/0 (true/false).

    Parameters:
      `strict` - whether null argument is converted as 0 or remains null
      `value` - argument
    Returns:
      a non-null value if argument can be represented by a long

  - ### asLongNumber

    protected Number asLongNumber(Object value)
    Checks if value class is a number that can be represented exactly in a long.

    For convenience, booleans are converted as 1/0 (true/false).

    Parameters:
      `value` - argument
    Returns:
      a non-null value if argument can be represented by a long

  - ### bitwiseAnd

    @Deprecated public final Object bitwiseAnd(Object lhs, Object rhs)
    Deprecated.
    3.0
    Use or overload and() instead.
    Parameters:
      `lhs` - left hand side
      `rhs` - right hand side
    Returns:
      lhs & rhs
    See Also:
      - `and(java.lang.Object, java.lang.Object)`

  - ### bitwiseOr

    @Deprecated public final Object bitwiseOr(Object lhs, Object rhs)
    Deprecated.
    3.0
    Use or overload or() instead.
    Parameters:
      `lhs` - left hand side
      `rhs` - right hand side
    Returns:
      lhs | rhs
    See Also:
      - `or(java.lang.Object, java.lang.Object)`

  - ### bitwiseXor

    @Deprecated public final Object bitwiseXor(Object lhs, Object rhs)
    Deprecated.
    3.0
    Use or overload xor() instead.
    Parameters:
      `lhs` - left hand side
      `rhs` - right hand side
    Returns:
      lhs ^ rhs
    See Also:
      - `xor(java.lang.Object, java.lang.Object)`

  - ### collectionContains

    protected Boolean collectionContains(Object collection, Object value)
    Checks whether a potential collection contains another.

    Made protected to make it easier to override if needed.

    Parameters:
      `collection` - the container which can be a collection or an array (even of primitive)
      `value` - the value which can be a collection or an array (even of primitive) or a singleton
    Returns:
      test result or null if there is no arithmetic solution

  - ### compare

    protected int compare(Object left, Object right, JexlOperator 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:
      `ArithmeticException` - if either left or right is null

  - ### compare

    @Deprecated protected int compare(Object left, Object right, String symbol)
    Deprecated.
    3.3
    Any override of this method (pre 3.3) should be modified to match the new signature.
    Parameters:
      `left` - left operand
      `right` - right operand
      `symbol` - the operator symbol
    Returns:
      -1 if left < right; +1 if left > right; 0 if left == right `compare(Object, Object, JexlOperator)`

  - ### complement

    public Object complement(Object val)
    Performs a bitwise complement.
    Parameters:
      `val` - the operand
    Returns:
      ~val

  - ### contains

    public Boolean contains(Object container, Object value)
    Test if left contains right (right matches/in left).

    Beware that this "contains " method arguments order is the opposite of the "in/matches" operator arguments. `x =~ y` means `y contains x` thus `contains(x, y)`.

    When this method returns null during evaluation, the operator code continues trying to find one through the uberspect.

    Parameters:
      `container` - the container
      `value` - the value
    Returns:
      test result or null if there is no arithmetic solution

  - ### controlNullNullOperands

    @Deprecated protected Object controlNullNullOperands()
    Deprecated.
    3.3
    The result of +,/,-,*,% when both operands are null.
    Returns:
      Integer(0) if lenient
    Throws:
      `JexlArithmetic.NullOperand` - if strict

  - ### controlNullNullOperands

    protected Object controlNullNullOperands(JexlOperator operator)
    The result of +,/,-,*,% when both operands are null.
    Parameters:
      `operator` - the actual operator
    Returns:
      Integer(0) if lenient
    Throws:
      `JexlArithmetic.NullOperand` - if strict-cast
    Since:
      3.3

  - ### controlNullOperand

    @Deprecated protected void controlNullOperand()
    Deprecated.
    3.3
    Throws an NullOperand exception if arithmetic is strict-cast.
    Throws:
      `JexlArithmetic.NullOperand` - if strict

  - ### controlNullOperand

    protected <T> T controlNullOperand(boolean strictCast, T defaultValue)
    Throws an NullOperand exception if arithmetic is strict-cast.

    This method is called by the cast methods (`toBoolean(boolean, Object)`, `toInteger(boolean, Object)`, `toDouble(boolean, Object)`, `toString(boolean, Object)`, `toBigInteger(boolean, Object)`, `toBigDecimal(boolean, Object)`) when they encounter a null argument.

    Type Parameters:
      `T` - the value type
    Parameters:
      `strictCast` - whether strict cast is required
      `defaultValue` - the default value to return, if not strict
    Returns:
      the default value is strict is false
    Throws:
      `JexlArithmetic.NullOperand` - if strict-cast
    Since:
      3.3

  - ### controlReturn

    public Object controlReturn(Object returned)
    The last method called before returning a result from a script execution.
    Parameters:
      `returned` - the returned value
    Returns:
      the controlled returned value

  - ### createRange

    public Iterable<?> createRange(Object from, Object to) throws ArithmeticException
    Creates a literal range.

    The default implementation only accepts integers and longs.

    Parameters:
      `from` - the included lower bound value (null if none)
      `to` - the included upper bound value (null if none)
    Returns:
      the range as an iterable
    Throws:
      `ArithmeticException` - as an option if creation fails

  - ### createWithOptions

    protected JexlArithmetic createWithOptions(boolean astrict, MathContext bigdContext, int bigdScale)
    Creates a JexlArithmetic instance. Called by options(...) method when another instance of the same class of arithmetic is required.
    Parameters:
      `astrict` - 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.
    Returns:
      default is a new JexlArithmetic instance
    Since:
      3.1
    See Also:
      - `options(org.apache.commons.jexl3.JexlEngine.Options)`

  - ### decrement

    public Object decrement(Object val)
    Decrements argument by 1.
    Parameters:
      `val` - the argument
    Returns:
      val - 1

  - ### divide

    public Object divide(Object left, Object right)
    Divide the left value by the right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left / right
    Throws:
      `ArithmeticException` - if right == 0

  - ### empty

    public Boolean empty(Object object)
    Check for emptiness of various types: Number, Collection, Array, Map, String.

    Override or overload this method to add new signatures to the size operators.

    Parameters:
      `object` - the object to check the emptiness of
    Returns:
      the boolean or false if object is not null
    Since:
      3.2

  - ### endsWith

    public Boolean endsWith(Object left, Object right)
    Test if left ends with right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left $= right if there is no arithmetic solution

  - ### equals

    public boolean equals(Object left, Object right)
    Test if left and right are equal.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      the test result

  - ### getMathContext

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

  - ### getMathScale

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

  - ### greaterThan

    public boolean greaterThan(Object left, Object right)
    Test if left > right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      the test result

  - ### greaterThanOrEqual

    public boolean greaterThanOrEqual(Object left, Object right)
    Test if left >= right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      the test result

  - ### increment

    public Object increment(Object val)
    Increments argument by 1.
    Parameters:
      `val` - the argument
    Returns:
      val + 1

  - ### increment

    protected Object increment(Object val, int incr)
    Add value to number argument.
    Parameters:
      `val` - the number
      `incr` - the value to add
    Returns:
      val + incr

  - ### evaluate

    public Object evaluate(org.apache.commons.logging.Log logger, Supplier<Object> arg)
    Evaluates a supplier argument, eventually catching and logging any JexlException.

    Used primarily by `empty(Object)` and `size(Object)` to guard argument evaluation. If evaluation succeeds, returns the supplier's result. If a `JexlException` occurs, logs a warning and returns `JexlEngine.TRY_FAILED` as an exception-occurred sentinel to the caller.

    This method is public to allow overriding.

    Parameters:
      `logger` - the logger for warning messages; may be null
      `arg` - the supplier providing the argument to evaluate
    Returns:
      the evaluated result on success or `JexlEngine.TRY_FAILED` on failure
    Since:
      3.6.3

  - ### isEmpty

    public Boolean isEmpty(Object object)
    Check for emptiness of various types: Number, Collection, Array, Map, String.
    Parameters:
      `object` - the object to check the emptiness of
    Returns:
      the boolean or null if there is no arithmetic solution

  - ### isEmpty

    public Boolean isEmpty(Object object, Boolean def)
    Check for emptiness of various types: Number, Collection, Array, Map, String.
    Parameters:
      `object` - the object to check the emptiness of
      `def` - the default value if object emptiness cannot be determined
    Returns:
      the boolean or null if there is no arithmetic solution

  - ### isFloatingPoint

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

  - ### isFloatingPointNumber

    protected boolean isFloatingPointNumber(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.

  - ### isNegateStable

    public boolean isNegateStable()
    Tests whether negate called with a given argument will always return the same result.

    This is used to determine whether negate results on number literals can be cached. If the result on calling negate with the same constant argument may change between calls, which means the function is not deterministic, this method must return false.

    Returns:
      true if negate is idempotent, false otherwise

  - ### isNullOperand

    protected boolean isNullOperand(Object value)
    Checks if an operand is considered null.
    Parameters:
      `value` - the operand
    Returns:
      true if operand is considered null

  - ### isNumberable

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

  - ### isPositivizeStable

    public boolean isPositivizeStable()
    Tests whether positivize called with a given argument will always return the same result.

    This is used to determine whether positivize results on number literals can be cached. If the result on calling positivize with the same constant argument may change between calls, which means the function is not deterministic, this method must return false.

    Returns:
      true if positivize is idempotent, false otherwise

  - ### isStrict

    public boolean isStrict()
    Checks whether this JexlArithmetic instance strictly considers null as an error when used as operand unexpectedly.
    Returns:
      true if strict, false if lenient

  - ### isStrict

    public boolean isStrict(JexlOperator operator)
    Tests whether this arithmetic considers a given operator as strict or null-safe.

    When an operator is strict, it does not accept null arguments when the arithmetic is strict. If null-safe (ie not-strict), the operator does accept null arguments even if the arithmetic itself is strict.

    The default implementation considers equal/not-equal operators as null-safe so one can check for null as in `if (myvar == null) {...}`. Note that this operator is used for equal and not-equal syntax. The complete list of operators that are not strict are (==, [], []=, ., .=, empty, size, contains).

    An arithmetic refining its strict behavior handling for more operators must declare which by overriding this method.

    Parameters:
      `operator` - the operator to check for null-argument(s) handling
    Returns:
      true if operator considers null arguments as errors, false if operator has appropriate semantics for null argument(s)

  - ### lessThan

    public boolean lessThan(Object left, Object right)
    Tests if left < right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      the test result

  - ### lessThanOrEqual

    public boolean lessThanOrEqual(Object left, Object right)
    Tests if left <= right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      the test result

  - ### logicalNot

    @Deprecated public final Object logicalNot(Object arg)
    Deprecated.
    3.0
    Use or overload not() instead.
    Parameters:
      `arg` - argument
    Returns:
      !arg
    See Also:
      - `not(java.lang.Object)`

  - ### mapBuilder

    @Deprecated public JexlArithmetic.MapBuilder mapBuilder(int size)
    Deprecated.
    3.3
    Creates a map-builder.
    Parameters:
      `size` - the number of elements in the map
    Returns:
      a map-builder instance

  - ### mapBuilder

    public JexlArithmetic.MapBuilder mapBuilder(int size, boolean extended)
    Called by the interpreter when evaluating a literal map.
    Parameters:
      `size` - the number of elements in the map
      `extended` - whether the map is extended or not
    Returns:
      the map builder

  - ### matches

    @Deprecated public final Object matches(Object lhs, Object rhs)
    Deprecated.
    3.0
    Use or overload contains() instead.
    Parameters:
      `lhs` - left hand side
      `rhs` - right hand side
    Returns:
      contains(rhs, lhs)
    See Also:
      - `contains(java.lang.Object, java.lang.Object)`

  - ### mod

    public Object mod(Object left, Object right)
    left value modulo right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left % right
    Throws:
      `ArithmeticException` - if right == 0.0

  - ### multiply

    public Object multiply(Object left, Object right)
    Multiply the left value by the right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left * right.

  - ### narrow

    public Number narrow(Number original)
    Given a Number, return 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(Class<?> narrow, Class<?> source)
    Tests whether we consider the narrow class as a potential candidate for narrowing the source.
    Parameters:
      `narrow` - the target narrow class
      `source` - the original source class
    Returns:
      true if attempt to narrow source to target is accepted

  - ### narrowArguments

    public boolean narrowArguments(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 occurred and args array has not been modified

  - ### narrowBigDecimal

    protected Number narrowBigDecimal(Object lhs, Object rhs, BigDecimal big)
    Given a BigDecimal, attempt to narrow it to an Integer or Long if it fits and one of the arguments is 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
      `big` - the BigDecimal to narrow
    Returns:
      an Integer or Long if narrowing is possible, the original BigDecimal otherwise

  - ### narrowBigInteger

    protected Number narrowBigInteger(Object lhs, Object rhs, BigInteger big)
    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
      `big` - the BigInteger to narrow
    Returns:
      an Integer or Long if narrowing is possible, the original BigInteger otherwise

  - ### narrowToLong

    protected <X extends Number> Number narrowToLong(Object lhs, Object rhs, X big, ToLongFunction<X> toLongFunction)
    Given a generic number, attempt to narrow it to an Integer or Long if it fits and one of the arguments is numberable.
    Type Parameters:
      `X` - the number type
    Parameters:
      `lhs` - the left-hand side operand that lead to the big result
      `rhs` - the right-hand side operand that lead to the big result
      `big` - the number to narrow
      `toLongFunction` - the function to convert the number to a long
    Returns:
      an Integer or Long if narrowing is possible, the original number otherwise

  - ### narrowLong

    protected Number narrowLong(Object lhs, Object rhs, long r)
    Given a long, attempt to narrow it to an int.

    Narrowing will only occur if no operand is a Long.

    Parameters:
      `lhs` - the left hand side operand that lead to the long result
      `rhs` - the right hand side operand that lead to the long result
      `r` - the long to narrow
    Returns:
      an Integer if narrowing is possible, the original Long otherwise

  - ### narrowNumber

    public Number narrowNumber(Number original, Class<?> narrow)
    Given a Number, return 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

  - ### negate

    public Object negate(Object val)
    Negates a value (unary minus for numbers).
    Parameters:
      `val` - the value to negate
    Returns:
      the negated value
    See Also:
      - `isNegateStable()`

  - ### not

    public Object not(Object val)
    Performs a logical not.
    Parameters:
      `val` - the operand
    Returns:
      !val

  - ### options

    public JexlArithmetic options(JexlContext context)
    Apply options to this arithmetic which eventually may create another instance.
    Parameters:
      `context` - the context that may extend `JexlContext.OptionsHandle` to use
    Returns:
      a new arithmetic instance or this
    Since:
      3.1
    See Also:
      - `createWithOptions(boolean, java.math.MathContext, int)`

  - ### options

    @Deprecated public JexlArithmetic options(JexlEngine.Options options)
    Deprecated.
    3.2
    Apply options to this arithmetic which eventually may create another instance.
    Parameters:
      `options` - the `JexlEngine.Options` to use
    Returns:
      an arithmetic with those options set
    See Also:
      - `createWithOptions(boolean, java.math.MathContext, int)`

  - ### options

    public JexlArithmetic options(JexlOptions options)
    Apply options to this arithmetic which eventually may create another instance.
    Parameters:
      `options` - the `JexlEngine.Options` to use
    Returns:
      an arithmetic with those options set
    See Also:
      - `createWithOptions(boolean, java.math.MathContext, int)`

  - ### or

    public Object or(Object left, Object right)
    Performs a bitwise or.
    Parameters:
      `left` - the left operand
      `right` - the right operator
    Returns:
      left | right

  - ### parseIdentifier

    public static Integer parseIdentifier(Object id)
    Parse an identifier which must be of the form: 0|([1-9][0-9]*)
    Parameters:
      `id` - the identifier
    Returns:
      an integer or null

  - ### positivize

    public Object positivize(Object val)
    Positivize value (unary plus for numbers).

    C/C++/C#/Java perform integral promotion of the operand, ie cast to int if type can be represented as int without loss of precision.

    Parameters:
      `val` - the value to positivize
    Returns:
      the positive value
    See Also:
      - `isPositivizeStable()`

  - ### roundBigDecimal

    protected BigDecimal roundBigDecimal(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

  - ### setBuilder

    @Deprecated public JexlArithmetic.SetBuilder setBuilder(int size)
    Deprecated.
    since 3.3.1
    Creates a set-builder.
    Parameters:
      `size` - the number of elements in the set
    Returns:
      a set-builder instance

  - ### setBuilder

    public JexlArithmetic.SetBuilder setBuilder(int size, boolean extended)
    Called by the interpreter when evaluating a literal set.
    Parameters:
      `size` - the number of elements in the set
      `extended` - whether the set is extended or not
    Returns:
      the array builder

  - ### shiftLeft

    public Object shiftLeft(Object left, Object right)
    Shifts a bit pattern to the right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left << right.

  - ### shiftRight

    public Object shiftRight(Object left, Object right)
    Shifts a bit pattern to the right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left >> right.

  - ### shiftRightUnsigned

    public Object shiftRightUnsigned(Object left, Object right)
    Shifts a bit pattern to the right unsigned.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left >>> right.

  - ### size

    public Integer size(Object object)
    Calculate the `size` of various types: Collection, Array, Map, String.
    Parameters:
      `object` - the object to get the size of
    Returns:
      the size of object, 0 if null, 1 if there is no better solution

  - ### size

    public Integer size(Object object, Integer def)
    Calculate the `size` of various types: Collection, Array, Map, String.
    Parameters:
      `object` - the object to get the size of
      `def` - the default value if object size cannot be determined
    Returns:
      the size of object or null if there is no arithmetic solution

  - ### startsWith

    public Boolean startsWith(Object left, Object right)
    Test if left starts with right.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left ^= right or null if there is no arithmetic solution

  - ### strictEquals

    public boolean strictEquals(Object left, Object right)
    Test if left and right are strictly equal.

    They must have the same class, comparable and the comparison returns 0.

    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      the test result

  - ### subtract

    public Object subtract(Object left, Object right)
    Subtract the right value from the left.
    Parameters:
      `left` - left argument
      `right` - right argument
    Returns:
      left - right.

  - ### testPredicate

    public boolean testPredicate(Object object)
    Test if a condition is true or false.
    Parameters:
      `object` - the object to use as condition
    Returns:
      true or false
    Since:
      3.3

  - ### toBigDecimal

    protected BigDecimal toBigDecimal(boolean strict, Object val)
    Coerce to a BigDecimal.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `strict` - true if the calling operator or casting is strict, false otherwise
      `val` - the object to be coerced.
    Returns:
      a BigDecimal.
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible
    Since:
      3.3

  - ### toBigDecimal

    public BigDecimal toBigDecimal(Object val)
    Coerce to a BigDecimal.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `val` - the object to be coerced.
    Returns:
      a BigDecimal.
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible

  - ### toBigInteger

    protected BigInteger toBigInteger(boolean strict, Object val)
    Coerce to a BigInteger.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `strict` - true if the calling operator or casting is strict, false otherwise
      `val` - the object to be coerced.
    Returns:
      a BigInteger
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible
    Since:
      3.3

  - ### toBigInteger

    public BigInteger toBigInteger(Object val)
    Coerce to a BigInteger.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `val` - the object to be coerced.
    Returns:
      a BigInteger
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible

  - ### toBoolean

    protected boolean toBoolean(boolean strict, Object val)
    Coerce to a primitive boolean.

    Double.NaN, null, "false" and empty string coerce to false.

    Parameters:
      `strict` - true if the calling operator or casting is strict, false otherwise
      `val` - value to coerce
    Returns:
      the boolean value if coercion is possible, true if value was not null.

  - ### toBoolean

    public boolean toBoolean(Object val)
    Coerce to a primitive boolean.

    Double.NaN, null, "false" and empty string coerce to false.

    Parameters:
      `val` - value to coerce
    Returns:
      the boolean value if coercion is possible, true if value was not null.

  - ### toDouble

    protected double toDouble(boolean strict, Object val)
    Coerce to a primitive double.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `strict` - true if the calling operator or casting is strict, false otherwise
      `val` - value to coerce.
    Returns:
      The double coerced value.
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible
    Since:
      3.3

  - ### toDouble

    public double toDouble(Object val)
    Coerce to a primitive double.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `val` - value to coerce.
    Returns:
      The double coerced value.
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible

  - ### toInteger

    protected int toInteger(boolean strict, Object val)
    Coerce to a primitive int.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `strict` - true if the calling operator or casting is strict, false otherwise
      `val` - value to coerce
    Returns:
      the value coerced to int
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible
    Since:
      3.3

  - ### toInteger

    public int toInteger(Object val)
    Coerce to a primitive int.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `val` - value to coerce
    Returns:
      the value coerced to int
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible

  - ### toLong

    protected long toLong(boolean strict, Object val)
    Coerce to a primitive long.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `strict` - true if the calling operator or casting is strict, false otherwise
      `val` - value to coerce
    Returns:
      the value coerced to long
    Throws:
      `ArithmeticException` - if value is null and mode is strict or if coercion is not possible
    Since:
      3.3

  - ### toLong

    public long toLong(Object val)
    Coerce to a primitive long.

    Double.NaN, null and empty string coerce to zero.

    Boolean false is 0, true is 1.

    Parameters:
      `val` - value to coerce
    Returns:
      the value coerced to long
    Throws:
      `ArithmeticException` - if value is null and mode is strict or if coercion is not possible

  - ### toString

    protected String toString(boolean strict, Object val)
    Coerce to a string.

    Double.NaN coerce to the empty string.

    Parameters:
      `strict` - true if the calling operator or casting is strict, false otherwise
      `val` - value to coerce.
    Returns:
      The String coerced value.
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible
    Since:
      3.3

  - ### toString

    public String toString(Object val)
    Coerce to a string.

    Double.NaN coerce to the empty string.

    Parameters:
      `val` - value to coerce.
    Returns:
      The String coerced value.
    Throws:
      `ArithmeticException` - if val is null and mode is strict or if coercion is not possible

  - ### xor

    public Object xor(Object left, Object right)
    Performs a bitwise xor.
    Parameters:
      `left` - the left operand
      `right` - the right operator
    Returns:
      left ^ right