diff --git a/org.springframework.expression/readme.txt b/org.springframework.expression/readme.txt index cc8fcd65fe4..6205f0d0cd3 100644 --- a/org.springframework.expression/readme.txt +++ b/org.springframework.expression/readme.txt @@ -33,6 +33,6 @@ Syntax - See LiteralTests for Date (4,5,6) - should date take an expression rather than be hardcoded in the grammar to take 2 strings only? - when doing arithmetic, eg. 8.4 / 4 and the user asks for an Integer return type - do we silently coerce or - say we cannot as it won't fit into an int? (see EvaluationTests.testMathOperatorDivide04) + say we cannot as it won't fit into an int? (see OperatorTests.testMathOperatorDivide04) - Is $index within projection/selection useful or just cute? - \ No newline at end of file +- All reals are represented as Doubles (so 1.25f is held internally as a double, can be converted to float when required though) - is that ok? \ No newline at end of file diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorPlus.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorPlus.java index a5dc2efd9db..2863e7b7c4d 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorPlus.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorPlus.java @@ -26,7 +26,6 @@ public class OperatorPlus extends Operator { super(payload); } - // TODO OperatorPlus is lacking a bit on implementation... @Override public Object getValue(ExpressionState state) throws EvaluationException { SpelNode leftOp = getLeftOperand(); diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/StandardTypeConverter.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/StandardTypeConverter.java index 74aaa82108b..9bdff71d212 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/StandardTypeConverter.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/StandardTypeConverter.java @@ -220,11 +220,15 @@ public class StandardTypeConverter implements TypeConverter { private static class ToFloatConverter implements StandardIndividualTypeConverter { public Object convert(Object value) throws SpelException { - return ((Double) value).floatValue(); + if (value instanceof Integer) { + return ((Integer)value).floatValue(); + } else { + return ((Double) value).floatValue(); + } } public Class[] getFrom() { - return new Class[] { Double.class }; + return new Class[] { Double.class, Integer.class }; } public Class getTo() { diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java index 654b27739c0..d7e1df9c7d3 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java @@ -137,42 +137,6 @@ public class EvaluationTests extends ExpressionTestCase { evaluate("27 matches '^.*2.*$'", true, Boolean.class); // conversion int>string } - // mathematical operators - public void testMathOperatorAdd01() { - evaluate("2 + 4", "6", Integer.class); - } - - public void testMathOperatorAdd02() { - evaluate("'hello' + ' ' + 'world'", "hello world", String.class); - } - - public void testMathOperatorSubtract01() { - evaluate("5 - 4", "1", Integer.class); - } - - public void testMathOperatorMultiply01() { - evaluate("7 * 4", "28", Integer.class); - } - - public void testMathOperatorDivide01() { - evaluate("8 / 4", "2", Integer.class); - } - - public void testMathOperatorDivide02() { - evaluate("8.4 / 4", "2.1", Double.class); - } - - public void testMathOperatorDivide03() { - evaluateAndAskForReturnType("8/4", new Double(2.0), Double.class); - } - - // public void testMathOperatorDivide04() { - // evaluateAndAskForReturnType("8.4 / 4", "2", Integer.class); - // } - - public void testMathOperatorModulus01() { - evaluate("7 % 4", "3", Integer.class); - } // mixing operators public void testMixingOperators01() { diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/LiteralTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/LiteralTests.java index 8ad4a8a763f..08e7b978893 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/LiteralTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/LiteralTests.java @@ -156,4 +156,10 @@ public class LiteralTests extends ExpressionTestCase { // int year convertable from number to string parseAndCheckError("date(2008,'yyyy').getTime()>0", SpelMessages.PARSE_PROBLEM); } + + public void testConversions() { + // getting the expression type to be what we want - either: + evaluate("(#foo=37;#foo.byteValue())",(byte)37,Byte.class); // calling byteValue() on Integer.class + evaluateAndAskForReturnType("(#foo=37;#foo)",(byte)37,Byte.class); // relying on registered type converters + } } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java index a9931a5cb51..4d904390ad2 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java @@ -62,12 +62,66 @@ public class OperatorTests extends ExpressionTestCase { evaluate("'a' * 5", "aaaaa", String.class); } - public void testMultiplyIntInt() { - evaluate("3 * 5", 15, Integer.class); - } - public void testMultiplyDoubleDoubleGivesDouble() { evaluate("3.0d * 5.0d", 15.0d, Double.class); } + public void testMathOperatorAdd02() { + evaluate("'hello' + ' ' + 'world'", "hello world", String.class); + } + + public void testIntegerArithmetic() { + evaluate("2 + 4", "6", Integer.class); + evaluate("5 - 4", "1", Integer.class); + evaluate("3 * 5", 15, Integer.class); + evaluate("3 / 1", 3, Integer.class); + evaluate("3 % 2", 1, Integer.class); + } + + public void testMathOperatorDivide_ConvertToDouble() { + evaluateAndAskForReturnType("8/4", new Double(2.0), Double.class); + } + + public void testMathOperatorDivide04_ConvertToFloat() { + evaluateAndAskForReturnType("8/4", new Float(2.0), Float.class); + } + + // public void testMathOperatorDivide04() { + // evaluateAndAskForReturnType("8.4 / 4", "2", Integer.class); + // } + + public void testDoubles() { + evaluate("3.0d + 5.0d", 8.0d, Double.class); + evaluate("3.0d - 5.0d", -2.0d, Double.class); + evaluate("3.0d * 5.0d", 15.0d, Double.class); + evaluate("3.0d / 5.0d", 0.6d, Double.class); + evaluate("6.0d % 3.5d", 2.5d, Double.class); + } + + public void testFloats() { + evaluate("3.0f + 5.0f", 8.0d, Double.class); + evaluate("3.0f - 5.0f", -2.0d, Double.class); + evaluate("3.0f * 5.0f", 15.0d, Double.class); + evaluate("3.0f / 5.0f", 0.6d, Double.class); + evaluate("5.0f % 3.1f", 1.9d, Double.class); + } + + public void testMixedOperands_FloatsAndDoubles() { + evaluate("3.0d + 5.0f", 8.0d, Double.class); + evaluate("3.0D - 5.0f", -2.0d, Double.class); + evaluate("3.0f * 5.0d", 15.0d, Double.class); + evaluate("3.0f / 5.0D", 0.6d, Double.class); + evaluate("5.0D % 3.1f", 1.9d, Double.class); + } + + public void testMixedOperands_DoublesAndInts() { + evaluate("3.0d + 5", 8.0d, Double.class); + evaluate("3.0D - 5", -2.0d, Double.class); + evaluate("3.0f * 5", 15.0d, Double.class); + evaluate("6.0f / 2", 3.0, Double.class); + evaluate("6.0f / 4", 1.5d, Double.class); + evaluate("5.0D % 3", 2.0d, Double.class); + evaluate("5.5D % 3", 2.5, Double.class); + } + }