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 2022/11/26 15:33:27 UTC
[commons-jexl] branch master updated: JEXL-384: revisit control implementation to better preserve previous JexlArithmetic (user) derived classes;
This is an automated email from the ASF dual-hosted git repository.
henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git
The following commit(s) were added to refs/heads/master by this push:
new 9681adbb JEXL-384: revisit control implementation to better preserve previous JexlArithmetic (user) derived classes;
new d5d9dbe1 Merge remote-tracking branch 'origin/master'
9681adbb is described below
commit 9681adbbd14362e751a21658f877f8aa919fed6e
Author: henrib <he...@apache.org>
AuthorDate: Sat Nov 26 16:33:19 2022 +0100
JEXL-384: revisit control implementation to better preserve previous JexlArithmetic (user) derived classes;
---
.../org/apache/commons/jexl3/JexlArithmetic.java | 251 +++++++++++----------
.../commons/jexl3/jexl342/OptionalArithmetic.java | 4 +
2 files changed, 135 insertions(+), 120 deletions(-)
diff --git a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
index 21bd8595..1be73232 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
@@ -365,91 +365,12 @@ public class JexlArithmetic {
}
/**
- * Coerce to a primitive boolean.
- * <p>Double.NaN, null, "false" and empty string coerce to false.</p>
- *
- * @param val value to coerce
- * @return the boolean value if coercion is possible, true if value was not null.
- */
- public boolean toBoolean(final Object val) {
- return toBoolean(strict, val);
- }
-
- /**
- * Coerce to a primitive int.
- * <p>Double.NaN, null and empty string coerce to zero.</p>
- * <p>Boolean false is 0, true is 1.</p>
- *
- * @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
+ * Checks if an operand is considered null.
+ * @apram val the operand
+ * @erturn true if operand is considered null
*/
- public int toInteger(final Object val) {
- return toInteger(strict, val);
- }
-
- /**
- * Coerce to a primitive long.
- * <p>Double.NaN, null and empty string coerce to zero.</p>
- * <p>Boolean false is 0, true is 1.</p>
- *
- * @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(final Object val) {
- return toLong(strict, val);
- }
-
- /**
- * Coerce to a BigInteger.
- * <p>Double.NaN, null and empty string coerce to zero.</p>
- * <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
- */
- public BigInteger toBigInteger(final Object val) {
- return toBigInteger(strict, val);
- }
-
- /**
- * 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 value to coerce.
- * @return The double coerced value.
- * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible
- */
- public double toDouble(final Object val) {
- return toDouble(strict, val);
- }
-
- /**
- * Coerce to a BigDecimal.
- * <p>Double.NaN, null and empty string coerce to zero.</p>
- * <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
- */
- public BigDecimal toBigDecimal(final Object val) {
- return toBigDecimal(strict, val);
- }
-
- /**
- * Coerce to a string.
- * <p>Double.NaN coerce to the empty string.</p>
- *
- * @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
- */
- public String toString(final Object val) {
- return toString(strict, val);
+ protected boolean isNullOperand(Object value) {
+ return value == null;
}
/**
@@ -460,12 +381,16 @@ public class JexlArithmetic {
* {@link #toBigDecimal(boolean, Object)}) when they encounter a null argument.</p>
*
* @param strictCast whether strict cast is required
+ * @param defaultValue the default value to return, if not strict
+ * @eeturn the default value is strict is false
* @throws JexlArithmetic.NullOperand if strict-cast
+ * @since 3.3
*/
- protected void controlNullOperand(boolean strictCast) {
+ protected <T> T controlNullOperand(boolean strictCast, T defaultValue) {
if (strictCast) {
throw new NullOperand();
}
+ return defaultValue;
}
/**
@@ -473,6 +398,7 @@ public class JexlArithmetic {
* @param strictCast whether strict-cast is required
* @return Integer(0) if lenient
* @throws JexlArithmetic.NullOperand if strict-cast
+ * @since 3.3
*/
protected Object controlNullNullOperands(boolean strictCast) {
if (strictCast ) {
@@ -490,10 +416,17 @@ public class JexlArithmetic {
* @return the boolean value if coercion is possible, true if value was not null.
*/
protected boolean toBoolean(final boolean strict, final Object val) {
- if (val == null) {
- controlNullOperand(strict);
- return false;
- }
+ return isNullOperand(val)? controlNullOperand(strict, false) : toBoolean(val);
+ }
+
+ /**
+ * Coerce to a primitive boolean.
+ * <p>Double.NaN, null, "false" and empty string coerce to false.</p>
+ *
+ * @param val value to coerce
+ * @return the boolean value if coercion is possible, true if value was not null.
+ */
+ public boolean toBoolean(final Object val) {
if (val instanceof Boolean) {
return ((Boolean) val);
}
@@ -508,6 +441,9 @@ public class JexlArithmetic {
final String strval = val.toString();
return !strval.isEmpty() && !"false".equals(strval);
}
+ if (val == null) {
+ return controlNullOperand(strict, false);
+ }
// non-null value is true
return true;
}
@@ -521,12 +457,22 @@ public class JexlArithmetic {
* @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
+ * @since 3.3
*/
protected int toInteger(final boolean strict, final Object val) {
- if (val == null) {
- controlNullOperand(strict);
- return 0;
- }
+ return isNullOperand(val)? controlNullOperand(strict, 0) : toInteger(val);
+ }
+
+ /**
+ * Coerce to a primitive int.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <p>Boolean false is 0, true is 1.</p>
+ *
+ * @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(final Object val) {
if (val instanceof Double) {
final double dval = (Double) val;
return Double.isNaN(dval)? 0 : (int) dval;
@@ -546,6 +492,9 @@ public class JexlArithmetic {
if (val instanceof Character) {
return ((Character) val);
}
+ if (val == null) {
+ return controlNullOperand(strict, 0);
+ }
throw new ArithmeticException("Integer coercion: "
+ val.getClass().getName() + ":(" + val + ")");
}
@@ -559,12 +508,22 @@ public class JexlArithmetic {
* @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
+ * @since 3.3
*/
protected long toLong(final boolean strict, final Object val) {
- if (val == null) {
- controlNullOperand(strict);
- return 0L;
- }
+ return isNullOperand(val)? controlNullOperand(strict, 0L) : toLong(val);
+ }
+
+ /**
+ * Coerce to a primitive long.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <p>Boolean false is 0, true is 1.</p>
+ *
+ * @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(final Object val) {
if (val instanceof Double) {
final double dval = (Double) val;
return Double.isNaN(dval)? 0L : (long) dval;
@@ -584,6 +543,9 @@ public class JexlArithmetic {
if (val instanceof Character) {
return ((Character) val);
}
+ if (val == null) {
+ return controlNullOperand(strict, 0L);
+ }
throw new ArithmeticException("Long coercion: "
+ val.getClass().getName() + ":(" + val + ")");
}
@@ -597,12 +559,22 @@ 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
+ * @since 3.3
*/
protected BigInteger toBigInteger(final boolean strict, final Object val) {
- if (val == null) {
- controlNullOperand(strict);
- return BigInteger.ZERO;
- }
+ return isNullOperand(val)? controlNullOperand(strict, BigInteger.ZERO) : toBigInteger(val);
+ }
+
+ /**
+ * Coerce to a BigInteger.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <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
+ */
+ public BigInteger toBigInteger(final Object val) {
if (val instanceof BigInteger) {
return (BigInteger) val;
}
@@ -632,6 +604,9 @@ public class JexlArithmetic {
final int i = ((Character) val);
return BigInteger.valueOf(i);
}
+ if (val == null) {
+ return controlNullOperand(strict, BigInteger.ZERO);
+ }
throw new ArithmeticException("BigInteger coercion: "
+ val.getClass().getName() + ":(" + val + ")");
}
@@ -645,15 +620,25 @@ 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
+ * @since 3.3
*/
protected BigDecimal toBigDecimal(final boolean strict, final Object val) {
+ return isNullOperand(val)? controlNullOperand(strict, BigDecimal.ZERO) : toBigDecimal(val);
+ }
+
+ /**
+ * Coerce to a BigDecimal.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <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
+ */
+ public BigDecimal toBigDecimal(final Object val) {
if (val instanceof BigDecimal) {
return roundBigDecimal((BigDecimal) val);
}
- if (val == null) {
- controlNullOperand(strict);
- return BigDecimal.ZERO;
- }
if (val instanceof Double) {
if (Double.isNaN(((Double) val))) {
return BigDecimal.ZERO;
@@ -680,6 +665,9 @@ public class JexlArithmetic {
final int i = ((Character) val);
return new BigDecimal(i);
}
+ if (val == null) {
+ return controlNullOperand(strict, BigDecimal.ZERO);
+ }
throw new ArithmeticException("BigDecimal coercion: "
+ val.getClass().getName() + ":(" + val + ")");
}
@@ -693,12 +681,22 @@ public class JexlArithmetic {
* @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
+ * @since 3.3
*/
protected double toDouble(final boolean strict, final Object val) {
- if (val == null) {
- controlNullOperand(strict);
- return 0;
- }
+ return isNullOperand(val)? controlNullOperand(strict, 0.d) : toDouble(val);
+ }
+
+ /**
+ * 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 value to coerce.
+ * @return The double coerced value.
+ * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible
+ */
+ public double toDouble(final Object val) {
if (val instanceof Double) {
return ((Double) val);
}
@@ -719,6 +717,9 @@ public class JexlArithmetic {
if (val instanceof Character) {
return ((Character) val);
}
+ if (val == null) {
+ return controlNullOperand(strict, 0.d);
+ }
throw new ArithmeticException("Double coercion: "
+ val.getClass().getName() + ":(" + val + ")");
}
@@ -731,21 +732,31 @@ public class JexlArithmetic {
* @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
+ * @since 3.3
*/
protected String toString(final boolean strict, final Object val) {
- if (val == null) {
- controlNullOperand(strict);
- return "";
- }
- if (!(val instanceof Double)) {
- return val.toString();
- }
- final Double dval = (Double) val;
- if (Double.isNaN(dval)) {
- return "";
+ return isNullOperand(val)? controlNullOperand(strict, "") : toString(val);
+ }
+
+ /**
+ * Coerce to a string.
+ * <p>Double.NaN coerce to the empty string.</p>
+ *
+ * @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
+ */
+ public String toString(final Object val) {
+ if (val instanceof Double) {
+ final Double dval = (Double) val;
+ if (Double.isNaN(dval)) {
+ return "";
+ }
+ return dval.toString();
}
- return dval.toString();
+ return val == null? controlNullOperand(strict, "") : val.toString();
}
+
/**
* Checks whether this JexlArithmetic instance
* strictly considers null as an error when used as operand unexpectedly.
diff --git a/src/test/java/org/apache/commons/jexl3/jexl342/OptionalArithmetic.java b/src/test/java/org/apache/commons/jexl3/jexl342/OptionalArithmetic.java
index 9bce162c..a3856cdb 100644
--- a/src/test/java/org/apache/commons/jexl3/jexl342/OptionalArithmetic.java
+++ b/src/test/java/org/apache/commons/jexl3/jexl342/OptionalArithmetic.java
@@ -57,6 +57,10 @@ public class OptionalArithmetic extends JexlArithmetic {
public Object controlReturn(Object returned) {
return star(returned);
}
+ @Override
+ protected boolean isNullOperand(Object val) {
+ return super.isNullOperand(star(val));
+ }
@Override
public boolean toBoolean(final Object val) {