diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpDec.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpDec.java index 0a5a1236d7e..895cfa3bc8a 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpDec.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpDec.java @@ -16,6 +16,8 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.Operation; import org.springframework.expression.TypedValue; @@ -29,6 +31,7 @@ import org.springframework.util.Assert; * appropriate exceptions if the operand in question does not support decrement. * * @author Andy Clement + * @author Giovanni Dall'Oglio Risso * @since 3.2 */ public class OpDec extends Operator { @@ -58,7 +61,11 @@ public class OpDec extends Operator { if (operandValue instanceof Number) { Number op1 = (Number) operandValue; - if (op1 instanceof Double) { + if (op1 instanceof BigDecimal) { + newValue = new TypedValue(((BigDecimal) op1).subtract(BigDecimal.ONE), + operandTypedValue.getTypeDescriptor()); + } + else if (op1 instanceof Double) { newValue = new TypedValue(op1.doubleValue() - 1.0d, operandTypedValue.getTypeDescriptor()); } @@ -79,7 +86,7 @@ public class OpDec extends Operator { operandTypedValue.getTypeDescriptor()); } } - if (newValue==null) { + if (newValue == null) { try { newValue = state.operate(Operation.SUBTRACT, returnValue.getValue(), 1); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpDivide.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpDivide.java index 844e2aa1d81..1f644f223f2 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpDivide.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpDivide.java @@ -16,20 +16,26 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; +import java.math.RoundingMode; + import org.springframework.expression.EvaluationException; import org.springframework.expression.Operation; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.ExpressionState; +import org.springframework.util.NumberUtils; /** * Implements division operator. * * @author Andy Clement * @author Juergen Hoeller + * @author Giovanni Dall'Oglio Risso * @since 3.0 */ public class OpDivide extends Operator { + public OpDivide(int pos, SpelNodeImpl... operands) { super("/", pos, operands); } @@ -37,26 +43,35 @@ public class OpDivide extends Operator { @Override public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { - Object operandOne = getLeftOperand().getValueInternal(state).getValue(); - Object operandTwo = getRightOperand().getValueInternal(state).getValue(); - if (operandOne instanceof Number && operandTwo instanceof Number) { - Number op1 = (Number) operandOne; - Number op2 = (Number) operandTwo; - if (op1 instanceof Double || op2 instanceof Double) { - return new TypedValue(op1.doubleValue() / op2.doubleValue()); + Object leftOperand = getLeftOperand().getValueInternal(state).getValue(); + Object rightOperand = getRightOperand().getValueInternal(state).getValue(); + + if (leftOperand instanceof Number && rightOperand instanceof Number) { + Number leftNumber = (Number) leftOperand; + Number rightNumber = (Number) rightOperand; + + if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { + BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); + BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); + int scale = Math.max(leftBigDecimal.scale(), rightBigDecimal.scale()); + return new TypedValue(leftBigDecimal.divide(rightBigDecimal, scale, RoundingMode.HALF_EVEN)); } - else if (op1 instanceof Float || op2 instanceof Float) { - return new TypedValue(op1.floatValue() / op2.floatValue()); + + if (leftNumber instanceof Double || rightNumber instanceof Double) { + return new TypedValue(leftNumber.doubleValue() / rightNumber.doubleValue()); } - else if (op1 instanceof Long || op2 instanceof Long) { - return new TypedValue(op1.longValue() / op2.longValue()); + if (leftNumber instanceof Float || rightNumber instanceof Float) { + return new TypedValue(leftNumber.floatValue() / rightNumber.floatValue()); } - else { - // TODO what about non-int result of the division? - return new TypedValue(op1.intValue() / op2.intValue()); + if (leftNumber instanceof Long || rightNumber instanceof Long) { + return new TypedValue(leftNumber.longValue() / rightNumber.longValue()); } + + // TODO what about non-int result of the division? + return new TypedValue(leftNumber.intValue() / rightNumber.intValue()); } - return state.operate(Operation.DIVIDE, operandOne, operandTwo); + + return state.operate(Operation.DIVIDE, leftOperand, rightOperand); } } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpGE.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpGE.java index 6e1294e461c..dbd0b21510b 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpGE.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpGE.java @@ -15,18 +15,23 @@ */ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.spel.ExpressionState; import org.springframework.expression.spel.support.BooleanTypedValue; +import org.springframework.util.NumberUtils; /** * Implements greater-than-or-equal operator. * * @author Andy Clement + * @author Giovanni Dall'Oglio Risso * @since 3.0 */ public class OpGE extends Operator { + public OpGE(int pos, SpelNodeImpl... operands) { super(">=", pos, operands); } @@ -39,18 +44,25 @@ public class OpGE extends Operator { if (left instanceof Number && right instanceof Number) { Number leftNumber = (Number) left; Number rightNumber = (Number) right; + + if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { + BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); + BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); + return BooleanTypedValue.forValue(leftBigDecimal.compareTo(rightBigDecimal) >= 0); + } + if (leftNumber instanceof Double || rightNumber instanceof Double) { return BooleanTypedValue.forValue(leftNumber.doubleValue() >= rightNumber.doubleValue()); } - else if (leftNumber instanceof Float || rightNumber instanceof Float) { + + if (leftNumber instanceof Float || rightNumber instanceof Float) { return BooleanTypedValue.forValue(leftNumber.floatValue() >= rightNumber.floatValue()); } - else if (leftNumber instanceof Long || rightNumber instanceof Long) { + + if (leftNumber instanceof Long || rightNumber instanceof Long) { return BooleanTypedValue.forValue(leftNumber.longValue() >= rightNumber.longValue()); } - else { - return BooleanTypedValue.forValue(leftNumber.intValue() >= rightNumber.intValue()); - } + return BooleanTypedValue.forValue(leftNumber.intValue() >= rightNumber.intValue()); } return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) >= 0); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpGT.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpGT.java index 769cc8d11aa..bf9babd6ee6 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpGT.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpGT.java @@ -16,14 +16,18 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.spel.ExpressionState; import org.springframework.expression.spel.support.BooleanTypedValue; +import org.springframework.util.NumberUtils; /** * Implements greater-than operator. * * @author Andy Clement + * @author Giovanni Dall'Oglio Risso * @since 3.0 */ public class OpGT extends Operator { @@ -38,21 +42,30 @@ public class OpGT extends Operator { public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException { Object left = getLeftOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue(); + if (left instanceof Number && right instanceof Number) { Number leftNumber = (Number) left; Number rightNumber = (Number) right; + + if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { + BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); + BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); + return BooleanTypedValue.forValue(leftBigDecimal.compareTo(rightBigDecimal) > 0); + } + if (leftNumber instanceof Double || rightNumber instanceof Double) { return BooleanTypedValue.forValue(leftNumber.doubleValue() > rightNumber.doubleValue()); } - else if (leftNumber instanceof Float || rightNumber instanceof Float) { + + if (leftNumber instanceof Float || rightNumber instanceof Float) { return BooleanTypedValue.forValue(leftNumber.floatValue() > rightNumber.floatValue()); } - else if (leftNumber instanceof Long || rightNumber instanceof Long) { + + if (leftNumber instanceof Long || rightNumber instanceof Long) { return BooleanTypedValue.forValue(leftNumber.longValue() > rightNumber.longValue()); } - else { - return BooleanTypedValue.forValue(leftNumber.intValue() > rightNumber.intValue()); - } + + return BooleanTypedValue.forValue(leftNumber.intValue() > rightNumber.intValue()); } return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) > 0); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpInc.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpInc.java index 43937ca9536..e1760e3bf8c 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpInc.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpInc.java @@ -16,6 +16,8 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.Operation; import org.springframework.expression.TypedValue; @@ -29,6 +31,7 @@ import org.springframework.util.Assert; * appropriate exceptions if the operand in question does not support increment. * * @author Andy Clement + * @author Giovanni Dall'Oglio Risso * @since 3.2 */ public class OpInc extends Operator { @@ -47,34 +50,38 @@ public class OpInc extends Operator { public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { SpelNodeImpl operand = getLeftOperand(); - ValueRef lvalue = operand.getValueRef(state); + ValueRef valueRef = operand.getValueRef(state); - final TypedValue operandTypedValue = lvalue.getValue(); - final Object operandValue = operandTypedValue.getValue(); - TypedValue returnValue = operandTypedValue; + final TypedValue typedValue = valueRef.getValue(); + final Object value = typedValue.getValue(); + TypedValue returnValue = typedValue; TypedValue newValue = null; - if (operandValue instanceof Number) { - Number op1 = (Number) operandValue; - if (op1 instanceof Double) { + if (value instanceof Number) { + Number op1 = (Number) value; + if (op1 instanceof BigDecimal) { + newValue = new TypedValue(((BigDecimal) op1).add(BigDecimal.ONE), + typedValue.getTypeDescriptor()); + } + else if (op1 instanceof Double) { newValue = new TypedValue(op1.doubleValue() + 1.0d, - operandTypedValue.getTypeDescriptor()); + typedValue.getTypeDescriptor()); } else if (op1 instanceof Float) { newValue = new TypedValue(op1.floatValue() + 1.0f, - operandTypedValue.getTypeDescriptor()); + typedValue.getTypeDescriptor()); } else if (op1 instanceof Long) { newValue = new TypedValue(op1.longValue() + 1L, - operandTypedValue.getTypeDescriptor()); + typedValue.getTypeDescriptor()); } else if (op1 instanceof Short) { newValue = new TypedValue(op1.shortValue() + (short) 1, - operandTypedValue.getTypeDescriptor()); + typedValue.getTypeDescriptor()); } else { newValue = new TypedValue(op1.intValue() + 1, - operandTypedValue.getTypeDescriptor()); + typedValue.getTypeDescriptor()); } } if (newValue == null) { @@ -93,7 +100,7 @@ public class OpInc extends Operator { // set the name value try { - lvalue.setValue(newValue.getValue()); + valueRef.setValue(newValue.getValue()); } catch (SpelEvaluationException see) { // if unable to set the value the operand is not writable (e.g. 1++ ) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpLE.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpLE.java index 47424db2044..d7991f816aa 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpLE.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpLE.java @@ -16,18 +16,23 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.spel.ExpressionState; import org.springframework.expression.spel.support.BooleanTypedValue; +import org.springframework.util.NumberUtils; /** * Implements the less-than-or-equal operator. * * @author Andy Clement + * @author Giovanni Dall'Oglio Risso * @since 3.0 */ public class OpLE extends Operator { + public OpLE(int pos, SpelNodeImpl... operands) { super("<=", pos, operands); } @@ -41,19 +46,28 @@ public class OpLE extends Operator { if (left instanceof Number && right instanceof Number) { Number leftNumber = (Number) left; Number rightNumber = (Number) right; + + if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { + BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); + BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); + return BooleanTypedValue.forValue(leftBigDecimal.compareTo(rightBigDecimal) <= 0); + } + if (leftNumber instanceof Double || rightNumber instanceof Double) { return BooleanTypedValue.forValue(leftNumber.doubleValue() <= rightNumber.doubleValue()); } - else if (leftNumber instanceof Float || rightNumber instanceof Float) { + + if (leftNumber instanceof Float || rightNumber instanceof Float) { return BooleanTypedValue.forValue(leftNumber.floatValue() <= rightNumber.floatValue()); } - else if (leftNumber instanceof Long || rightNumber instanceof Long) { + + if (leftNumber instanceof Long || rightNumber instanceof Long) { return BooleanTypedValue.forValue(leftNumber.longValue() <= rightNumber.longValue()); } - else { - return BooleanTypedValue.forValue(leftNumber.intValue() <= rightNumber.intValue()); - } + + return BooleanTypedValue.forValue(leftNumber.intValue() <= rightNumber.intValue()); } + return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) <= 0); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpLT.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpLT.java index 1027a0c026d..3e13c99fff9 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpLT.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpLT.java @@ -16,14 +16,18 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.spel.ExpressionState; import org.springframework.expression.spel.support.BooleanTypedValue; +import org.springframework.util.NumberUtils; /** * Implements the less-than operator. * * @author Andy Clement + * @author Giovanni Dall'Oglio Risso * @since 3.0 */ public class OpLT extends Operator { @@ -43,18 +47,26 @@ public class OpLT extends Operator { if (left instanceof Number && right instanceof Number) { Number leftNumber = (Number) left; Number rightNumber = (Number) right; + + if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { + BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); + BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); + return BooleanTypedValue.forValue(leftBigDecimal.compareTo(rightBigDecimal) < 0); + } + if (leftNumber instanceof Double || rightNumber instanceof Double) { return BooleanTypedValue.forValue(leftNumber.doubleValue() < rightNumber.doubleValue()); } - else if (leftNumber instanceof Float || rightNumber instanceof Float) { + + if (leftNumber instanceof Float || rightNumber instanceof Float) { return BooleanTypedValue.forValue(leftNumber.floatValue() < rightNumber.floatValue()); } - else if (leftNumber instanceof Long || rightNumber instanceof Long) { + + if (leftNumber instanceof Long || rightNumber instanceof Long) { return BooleanTypedValue.forValue(leftNumber.longValue() < rightNumber.longValue()); } - else { - return BooleanTypedValue.forValue(leftNumber.intValue() < rightNumber.intValue()); - } + + return BooleanTypedValue.forValue(leftNumber.intValue() < rightNumber.intValue()); } return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) < 0); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMinus.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMinus.java index 143dfd9014a..b283b7278de 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMinus.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMinus.java @@ -16,33 +16,40 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.Operation; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.ExpressionState; +import org.springframework.util.NumberUtils; /** * The minus operator supports: * - * It can be used as a unary operator for numbers (double/long/int). The standard - * promotions are performed when the operand types vary (double-int=double). For other - * options it defers to the registered overloader. + * It can be used as a unary operator for numbers ({@code BigDecimal}/double/long/int). + * The standard promotions are performed when the operand types vary (double-int=double). + * For other options it defers to the registered overloader. * * @author Andy Clement + * @author Giovanni Dall'Oglio Risso * @since 3.0 */ public class OpMinus extends Operator { + public OpMinus(int pos, SpelNodeImpl... operands) { super("-", pos, operands); } + @Override public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { @@ -53,6 +60,12 @@ public class OpMinus extends Operator { Object operand = leftOp.getValueInternal(state).getValue(); if (operand instanceof Number) { Number n = (Number) operand; + + if (operand instanceof BigDecimal) { + BigDecimal bdn = (BigDecimal) n; + return new TypedValue(bdn.negate()); + } + if (operand instanceof Double) { return new TypedValue(0 - n.doubleValue()); } @@ -64,6 +77,7 @@ public class OpMinus extends Operator { if (operand instanceof Long) { return new TypedValue(0 - n.longValue()); } + return new TypedValue(0 - n.intValue()); } @@ -74,21 +88,28 @@ public class OpMinus extends Operator { Object right = rightOp.getValueInternal(state).getValue(); if (left instanceof Number && right instanceof Number) { - Number op1 = (Number) left; - Number op2 = (Number) right; - if (op1 instanceof Double || op2 instanceof Double) { - return new TypedValue(op1.doubleValue() - op2.doubleValue()); + Number leftNumber = (Number) left; + Number rightNumber = (Number) right; + + if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { + BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); + BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); + return new TypedValue(leftBigDecimal.subtract(rightBigDecimal)); + } + + if (leftNumber instanceof Double || rightNumber instanceof Double) { + return new TypedValue(leftNumber.doubleValue() - rightNumber.doubleValue()); } - if (op1 instanceof Float || op2 instanceof Float) { - return new TypedValue(op1.floatValue() - op2.floatValue()); + if (leftNumber instanceof Float || rightNumber instanceof Float) { + return new TypedValue(leftNumber.floatValue() - rightNumber.floatValue()); } - if (op1 instanceof Long || op2 instanceof Long) { - return new TypedValue(op1.longValue() - op2.longValue()); + if (leftNumber instanceof Long || rightNumber instanceof Long) { + return new TypedValue(leftNumber.longValue() - rightNumber.longValue()); } - return new TypedValue(op1.intValue() - op2.intValue()); + return new TypedValue(leftNumber.intValue() - rightNumber.intValue()); } else if (left instanceof String && right instanceof Integer && ((String) left).length() == 1) { diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpModulus.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpModulus.java index 48b511229d7..c1c71326c4d 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpModulus.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpModulus.java @@ -16,19 +16,24 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.Operation; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.ExpressionState; +import org.springframework.util.NumberUtils; /** * Implements the modulus operator. * * @author Andy Clement + * @author Giovanni Dall'Oglio Risso * @since 3.0 */ public class OpModulus extends Operator { + public OpModulus(int pos, SpelNodeImpl... operands) { super("%", pos, operands); } @@ -36,25 +41,34 @@ public class OpModulus extends Operator { @Override public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { - Object operandOne = getLeftOperand().getValueInternal(state).getValue(); - Object operandTwo = getRightOperand().getValueInternal(state).getValue(); - if (operandOne instanceof Number && operandTwo instanceof Number) { - Number op1 = (Number) operandOne; - Number op2 = (Number) operandTwo; - if (op1 instanceof Double || op2 instanceof Double) { - return new TypedValue(op1.doubleValue() % op2.doubleValue()); + Object leftOperand = getLeftOperand().getValueInternal(state).getValue(); + Object rightOperand = getRightOperand().getValueInternal(state).getValue(); + if (leftOperand instanceof Number && rightOperand instanceof Number) { + Number leftNumber = (Number) leftOperand; + Number rightNumber = (Number) rightOperand; + + if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { + BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); + BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); + return new TypedValue(leftBigDecimal.remainder(rightBigDecimal)); } - else if (op1 instanceof Float || op2 instanceof Float) { - return new TypedValue(op1.floatValue() % op2.floatValue()); + + if (leftNumber instanceof Double || rightNumber instanceof Double) { + return new TypedValue(leftNumber.doubleValue() % rightNumber.doubleValue()); } - else if (op1 instanceof Long || op2 instanceof Long) { - return new TypedValue(op1.longValue() % op2.longValue()); + + if (leftNumber instanceof Float || rightNumber instanceof Float) { + return new TypedValue(leftNumber.floatValue() % rightNumber.floatValue()); } - else { - return new TypedValue(op1.intValue() % op2.intValue()); + + if (leftNumber instanceof Long || rightNumber instanceof Long) { + return new TypedValue(leftNumber.longValue() % rightNumber.longValue()); } + + return new TypedValue(leftNumber.intValue() % rightNumber.intValue()); } - return state.operate(Operation.MODULUS, operandOne, operandTwo); + + return state.operate(Operation.MODULUS, leftOperand, rightOperand); } } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java index e795dff8b8c..870ceb1fdf8 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java @@ -16,20 +16,24 @@ package org.springframework.expression.spel.ast; +import java.math.BigDecimal; + import org.springframework.expression.EvaluationException; import org.springframework.expression.Operation; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.ExpressionState; +import org.springframework.util.NumberUtils; /** * Implements the {@code multiply} operator. * *

Conversions and promotions are handled as defined in * Section - * 5.6.2 of the Java Language Specification: + * 5.6.2 of the Java Language Specification, with the addiction of {@code BigDecimal} management: * *

If any of the operands is of a reference type, unboxing conversion (Section 5.1.8) * is performed. Then:
+ * If either operand is of type {@code BigDecimal}, the other is converted to {@code BigDecimal}.
* If either operand is of type double, the other is converted to double.
* Otherwise, if either operand is of type float, the other is converted to float.
* Otherwise, if either operand is of type long, the other is converted to long.
@@ -37,10 +41,12 @@ import org.springframework.expression.spel.ExpressionState; * * @author Andy Clement * @author Sam Brannen + * @author Giovanni Dall'Oglio Risso * @since 3.0 */ public class OpMultiply extends Operator { + public OpMultiply(int pos, SpelNodeImpl... operands) { super("*", pos, operands); } @@ -52,6 +58,7 @@ public class OpMultiply extends Operator { * for types not supported here. *

Supported operand types: *