EQ/NE do not fail in case of a Comparable mismatch and apply a specific CharSequence equality check

Issue: SPR-11708
This commit is contained in:
Juergen Hoeller 2014-04-21 23:29:40 +02:00
parent 566e0fb317
commit 66bae99d86
6 changed files with 256 additions and 178 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,22 +21,19 @@ import org.springframework.expression.spel.ExpressionState;
import org.springframework.expression.spel.support.BooleanTypedValue;
/**
* Implements equality operator.
* Implements the equality operator.
*
* @author Andy Clement
* @since 3.0
*/
public class OpEQ extends Operator {
public OpEQ(int pos, SpelNodeImpl... operands) {
super("==", pos, operands);
}
@Override
public BooleanTypedValue getValueInternal(ExpressionState state)
throws EvaluationException {
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Object left = getLeftOperand().getValueInternal(state).getValue();
Object right = getRightOperand().getValueInternal(state).getValue();
return BooleanTypedValue.forValue(equalityCheck(state, left, right));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,20 +24,19 @@ import org.springframework.expression.spel.support.BooleanTypedValue;
import org.springframework.util.NumberUtils;
/**
* Implements greater-than operator.
* Implements the greater-than operator.
*
* @author Andy Clement
* @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso
* @since 3.0
*/
public class OpGT extends Operator {
public OpGT(int pos, SpelNodeImpl... operands) {
super(">", pos, operands);
}
@Override
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Object left = getLeftOperand().getValueInternal(state).getValue();
@ -67,6 +66,12 @@ public class OpGT extends Operator {
return BooleanTypedValue.forValue(leftNumber.intValue() > rightNumber.intValue());
}
if (left instanceof CharSequence && right instanceof CharSequence) {
left = left.toString();
right = right.toString();
}
return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) > 0);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,20 +27,18 @@ import org.springframework.util.NumberUtils;
* Implements the less-than operator.
*
* @author Andy Clement
* @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso
* @since 3.0
*/
public class OpLT extends Operator {
public OpLT(int pos, SpelNodeImpl... operands) {
super("<", pos, operands);
}
@Override
public BooleanTypedValue getValueInternal(ExpressionState state)
throws EvaluationException {
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Object left = getLeftOperand().getValueInternal(state).getValue();
Object right = getRightOperand().getValueInternal(state).getValue();
@ -68,6 +66,12 @@ public class OpLT extends Operator {
return BooleanTypedValue.forValue(leftNumber.intValue() < rightNumber.intValue());
}
if (left instanceof CharSequence && right instanceof CharSequence) {
left = left.toString();
right = right.toString();
}
return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) < 0);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,12 +28,10 @@ import org.springframework.expression.spel.support.BooleanTypedValue;
*/
public class OpNE extends Operator {
public OpNE(int pos, SpelNodeImpl... operands) {
super("!=", pos, operands);
}
@Override
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Object left = getLeftOperand().getValueInternal(state).getValue();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,15 +19,17 @@ package org.springframework.expression.spel.ast;
import java.math.BigDecimal;
import org.springframework.expression.spel.ExpressionState;
import org.springframework.util.ClassUtils;
import org.springframework.util.NumberUtils;
import org.springframework.util.ObjectUtils;
/**
* Common supertype for operators that operate on either one or two operands. In the case
* of multiply or divide there would be two operands, but for unary plus or minus, there
* is only one.
* Common supertype for operators that operate on either one or two operands.
* In the case of multiply or divide there would be two operands, but for
* unary plus or minus, there is only one.
*
* @author Andy Clement
* @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso
* @since 3.0
*/
@ -70,6 +72,7 @@ public abstract class Operator extends SpelNodeImpl {
return sb.toString();
}
protected boolean equalityCheck(ExpressionState state, Object left, Object right) {
if (left instanceof Number && right instanceof Number) {
Number leftNumber = (Number) left;
@ -96,11 +99,22 @@ public abstract class Operator extends SpelNodeImpl {
return (leftNumber.intValue() == rightNumber.intValue());
}
if (left != null && (left instanceof Comparable)) {
return (state.getTypeComparator().compare(left, right) == 0);
if (left instanceof CharSequence && right instanceof CharSequence) {
return left.toString().equals(right.toString());
}
return ObjectUtils.nullSafeEquals(left, right);
if (ObjectUtils.nullSafeEquals(left, right)) {
return true;
}
if (left instanceof Comparable && right instanceof Comparable) {
Class<?> ancestor = ClassUtils.determineCommonAncestor(left.getClass(), right.getClass());
if (ancestor != null && Comparable.class.isAssignableFrom(ancestor)) {
return (state.getTypeComparator().compare(left, right) == 0);
}
}
return false;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,121 +16,24 @@
package org.springframework.expression.spel;
import static org.junit.Assert.assertEquals;
import java.math.BigDecimal;
import org.junit.Test;
import org.springframework.expression.spel.ast.Operator;
import org.springframework.expression.spel.standard.SpelExpression;
import static org.junit.Assert.*;
/**
* Tests the evaluation of expressions using relational operators.
*
* @author Andy Clement
* @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso
*/
public class OperatorTests extends AbstractExpressionTests {
@Test
public void testIntegerLiteral() {
evaluate("3", 3, Integer.class);
}
@Test
public void testRealLiteral() {
evaluate("3.5", 3.5d, Double.class);
}
@Test
public void testLessThan() {
evaluate("5 < 5", false, Boolean.class);
evaluate("3 < 5", true, Boolean.class);
evaluate("5 < 3", false, Boolean.class);
evaluate("3L < 5L", true, Boolean.class);
evaluate("5L < 3L", false, Boolean.class);
evaluate("3.0d < 5.0d", true, Boolean.class);
evaluate("5.0d < 3.0d", false, Boolean.class);
evaluate("'abc' < 'def'",true,Boolean.class);
evaluate("'def' < 'abc'",false,Boolean.class);
evaluate("new java.math.BigDecimal('3') < new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') < new java.math.BigDecimal('3')", false, Boolean.class);
evaluate("3 < new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') < 5", true, Boolean.class);
evaluate("3L < new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3.0d < new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3L < new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d < new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d < new java.math.BigDecimal('3.0')", false, Boolean.class);
evaluate("3 lt 5", true, Boolean.class);
evaluate("5 lt 3", false, Boolean.class);
evaluate("3L lt 5L", true, Boolean.class);
evaluate("5L lt 3L", false, Boolean.class);
evaluate("3.0d lT 5.0d", true, Boolean.class);
evaluate("5.0d Lt 3.0d", false, Boolean.class);
evaluate("'abc' LT 'def'",true,Boolean.class);
evaluate("'def' lt 'abc'",false,Boolean.class);
evaluate("new java.math.BigDecimal('3') lt new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') lt new java.math.BigDecimal('3')", false, Boolean.class);
evaluate("3 lt new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') lt 5", true, Boolean.class);
evaluate("3L lt new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3.0d lt new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3L lt new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d lt new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d lt new java.math.BigDecimal('3.0')", false, Boolean.class);
}
@Test
public void testLessThanOrEqual() {
evaluate("3 <= 5", true, Boolean.class);
evaluate("5 <= 3", false, Boolean.class);
evaluate("6 <= 6", true, Boolean.class);
evaluate("3L <= 5L", true, Boolean.class);
evaluate("5L <= 3L", false, Boolean.class);
evaluate("5L <= 5L", true, Boolean.class);
evaluate("3.0d <= 5.0d", true, Boolean.class);
evaluate("5.0d <= 3.0d", false, Boolean.class);
evaluate("5.0d <= 5.0d", true, Boolean.class);
evaluate("'abc' <= 'def'",true,Boolean.class);
evaluate("'def' <= 'abc'",false,Boolean.class);
evaluate("'abc' <= 'abc'",true,Boolean.class);
evaluate("new java.math.BigDecimal('5') <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') <= new java.math.BigDecimal('3')", false, Boolean.class);
evaluate("3 <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') <= 5", true, Boolean.class);
evaluate("3L <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3.0d <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3L <= new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d <= new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d <= new java.math.BigDecimal('3.0')", true, Boolean.class);
evaluate("3 le 5", true, Boolean.class);
evaluate("5 le 3", false, Boolean.class);
evaluate("6 Le 6", true, Boolean.class);
evaluate("3L lE 5L", true, Boolean.class);
evaluate("5L LE 3L", false, Boolean.class);
evaluate("5L le 5L", true, Boolean.class);
evaluate("3.0d LE 5.0d", true, Boolean.class);
evaluate("5.0d lE 3.0d", false, Boolean.class);
evaluate("5.0d Le 5.0d", true, Boolean.class);
evaluate("'abc' Le 'def'",true,Boolean.class);
evaluate("'def' LE 'abc'",false,Boolean.class);
evaluate("'abc' le 'abc'",true,Boolean.class);
evaluate("new java.math.BigDecimal('5') le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') le new java.math.BigDecimal('3')", false, Boolean.class);
evaluate("3 le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') le 5", true, Boolean.class);
evaluate("3L le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3.0d le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3L le new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d le new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d le new java.math.BigDecimal('3.0')", true, Boolean.class);
}
@Test
public void testEqual() {
evaluate("3 == 5", false, Boolean.class);
@ -138,7 +41,6 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("6 == 6", true, Boolean.class);
evaluate("3.0f == 5.0f", false, Boolean.class);
evaluate("3.0f == 3.0f", true, Boolean.class);
evaluate("'abc' == null", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') == new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') == new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') == new java.math.BigDecimal('3')", false, Boolean.class);
@ -149,13 +51,19 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("3L == new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d == new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d == new java.math.BigDecimal('3.0')", true, Boolean.class);
evaluate("3.0f == 3.0d", true, Boolean.class);
evaluate("10 == '10'", false, Boolean.class);
evaluate("'abc' == 'abc'", true, Boolean.class);
evaluate("'abc' == new java.lang.StringBuilder('abc')", true, Boolean.class);
evaluate("'abc' == 'def'", false, Boolean.class);
evaluate("'abc' == null", false, Boolean.class);
evaluate("new org.springframework.expression.spel.OperatorTests$SubComparable() == new org.springframework.expression.spel.OperatorTests$OtherSubComparable()", true, Boolean.class);
evaluate("3 eq 5", false, Boolean.class);
evaluate("5 eQ 3", false, Boolean.class);
evaluate("6 Eq 6", true, Boolean.class);
evaluate("3.0f eq 5.0f", false, Boolean.class);
evaluate("3.0f EQ 3.0f", true, Boolean.class);
evaluate("'abc' EQ null", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') eq new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') eq new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') eq new java.math.BigDecimal('3')", false, Boolean.class);
@ -166,6 +74,13 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("3L eq new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d eq new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d eq new java.math.BigDecimal('3.0')", true, Boolean.class);
evaluate("3.0f eq 3.0d", true, Boolean.class);
evaluate("10 eq '10'", false, Boolean.class);
evaluate("'abc' eq 'abc'", true, Boolean.class);
evaluate("'abc' eq new java.lang.StringBuilder('abc')", true, Boolean.class);
evaluate("'abc' eq 'def'", false, Boolean.class);
evaluate("'abc' eq null", false, Boolean.class);
evaluate("new org.springframework.expression.spel.OperatorTests$SubComparable() eq new org.springframework.expression.spel.OperatorTests$OtherSubComparable()", true, Boolean.class);
}
@Test
@ -185,6 +100,13 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("3L != new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d != new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d != new java.math.BigDecimal('3.0')", false, Boolean.class);
evaluate("3.0f != 3.0d", false, Boolean.class);
evaluate("10 != '10'", true, Boolean.class);
evaluate("'abc' != 'abc'", false, Boolean.class);
evaluate("'abc' != new java.lang.StringBuilder('abc')", false, Boolean.class);
evaluate("'abc' != 'def'", true, Boolean.class);
evaluate("'abc' != null", true, Boolean.class);
evaluate("new org.springframework.expression.spel.OperatorTests$SubComparable() != new org.springframework.expression.spel.OperatorTests$OtherSubComparable()", false, Boolean.class);
evaluate("3 ne 5", true, Boolean.class);
evaluate("5 nE 3", true, Boolean.class);
@ -201,6 +123,145 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("3L ne new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d ne new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d ne new java.math.BigDecimal('3.0')", false, Boolean.class);
evaluate("3.0f ne 3.0d", false, Boolean.class);
evaluate("10 ne '10'", true, Boolean.class);
evaluate("'abc' ne 'abc'", false, Boolean.class);
evaluate("'abc' ne new java.lang.StringBuilder('abc')", false, Boolean.class);
evaluate("'abc' ne 'def'", true, Boolean.class);
evaluate("'abc' ne null", true, Boolean.class);
evaluate("new org.springframework.expression.spel.OperatorTests$SubComparable() ne new org.springframework.expression.spel.OperatorTests$OtherSubComparable()", false, Boolean.class);
}
@Test
public void testLessThan() {
evaluate("5 < 5", false, Boolean.class);
evaluate("3 < 5", true, Boolean.class);
evaluate("5 < 3", false, Boolean.class);
evaluate("3L < 5L", true, Boolean.class);
evaluate("5L < 3L", false, Boolean.class);
evaluate("3.0d < 5.0d", true, Boolean.class);
evaluate("5.0d < 3.0d", false, Boolean.class);
evaluate("new java.math.BigDecimal('3') < new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') < new java.math.BigDecimal('3')", false, Boolean.class);
evaluate("3 < new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') < 5", true, Boolean.class);
evaluate("3L < new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3.0d < new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3L < new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d < new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d < new java.math.BigDecimal('3.0')", false, Boolean.class);
evaluate("'abc' < 'def'", true, Boolean.class);
evaluate("'abc' < new java.lang.StringBuilder('def')", true, Boolean.class);
evaluate("'def' < 'abc'", false, Boolean.class);
evaluate("3 lt 5", true, Boolean.class);
evaluate("5 lt 3", false, Boolean.class);
evaluate("3L lt 5L", true, Boolean.class);
evaluate("5L lt 3L", false, Boolean.class);
evaluate("3.0d lT 5.0d", true, Boolean.class);
evaluate("5.0d Lt 3.0d", false, Boolean.class);
evaluate("new java.math.BigDecimal('3') lt new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') lt new java.math.BigDecimal('3')", false, Boolean.class);
evaluate("3 lt new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') lt 5", true, Boolean.class);
evaluate("3L lt new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3.0d lt new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3L lt new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d lt new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d lt new java.math.BigDecimal('3.0')", false, Boolean.class);
evaluate("'abc' LT 'def'", true, Boolean.class);
evaluate("'abc' lt new java.lang.StringBuilder('def')", true, Boolean.class);
evaluate("'def' lt 'abc'", false, Boolean.class);
}
@Test
public void testLessThanOrEqual() {
evaluate("3 <= 5", true, Boolean.class);
evaluate("5 <= 3", false, Boolean.class);
evaluate("6 <= 6", true, Boolean.class);
evaluate("3L <= 5L", true, Boolean.class);
evaluate("5L <= 3L", false, Boolean.class);
evaluate("5L <= 5L", true, Boolean.class);
evaluate("3.0d <= 5.0d", true, Boolean.class);
evaluate("5.0d <= 3.0d", false, Boolean.class);
evaluate("5.0d <= 5.0d", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') <= new java.math.BigDecimal('3')", false, Boolean.class);
evaluate("3 <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') <= 5", true, Boolean.class);
evaluate("3L <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3.0d <= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3L <= new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d <= new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d <= new java.math.BigDecimal('3.0')", true, Boolean.class);
evaluate("'abc' <= 'def'", true, Boolean.class);
evaluate("'def' <= 'abc'", false, Boolean.class);
evaluate("'abc' <= 'abc'", true, Boolean.class);
evaluate("3 le 5", true, Boolean.class);
evaluate("5 le 3", false, Boolean.class);
evaluate("6 Le 6", true, Boolean.class);
evaluate("3L lE 5L", true, Boolean.class);
evaluate("5L LE 3L", false, Boolean.class);
evaluate("5L le 5L", true, Boolean.class);
evaluate("3.0d LE 5.0d", true, Boolean.class);
evaluate("5.0d lE 3.0d", false, Boolean.class);
evaluate("5.0d Le 5.0d", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') le new java.math.BigDecimal('3')", false, Boolean.class);
evaluate("3 le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') le 5", true, Boolean.class);
evaluate("3L le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3.0d le new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("3L le new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d le new java.math.BigDecimal('3.1')", true, Boolean.class);
evaluate("3.0d le new java.math.BigDecimal('3.0')", true, Boolean.class);
evaluate("'abc' Le 'def'", true, Boolean.class);
evaluate("'def' LE 'abc'", false, Boolean.class);
evaluate("'abc' le 'abc'", true, Boolean.class);
}
@Test
public void testGreaterThan() {
evaluate("3 > 5", false, Boolean.class);
evaluate("5 > 3", true, Boolean.class);
evaluate("3L > 5L", false, Boolean.class);
evaluate("5L > 3L", true, Boolean.class);
evaluate("3.0d > 5.0d", false, Boolean.class);
evaluate("5.0d > 3.0d", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') > new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') > new java.math.BigDecimal('3')", true, Boolean.class);
evaluate("3 > new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('3') > 5", false, Boolean.class);
evaluate("3L > new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("3.0d > new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("3L > new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d > new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d > new java.math.BigDecimal('3.0')", false, Boolean.class);
evaluate("'abc' > 'def'", false, Boolean.class);
evaluate("'abc' > new java.lang.StringBuilder('def')", false, Boolean.class);
evaluate("'def' > 'abc'", true, Boolean.class);
evaluate("3 gt 5", false, Boolean.class);
evaluate("5 gt 3", true, Boolean.class);
evaluate("3L gt 5L", false, Boolean.class);
evaluate("5L gt 3L", true, Boolean.class);
evaluate("3.0d gt 5.0d", false, Boolean.class);
evaluate("5.0d gT 3.0d", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') gt new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') gt new java.math.BigDecimal('3')", true, Boolean.class);
evaluate("3 gt new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('3') gt 5", false, Boolean.class);
evaluate("3L gt new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("3.0d gt new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("3L gt new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d gt new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d gt new java.math.BigDecimal('3.0')", false, Boolean.class);
evaluate("'abc' Gt 'def'", false, Boolean.class);
evaluate("'abc' gt new java.lang.StringBuilder('def')", false, Boolean.class);
evaluate("'def' GT 'abc'", true, Boolean.class);
}
@Test
@ -213,10 +274,7 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("5L >= 5L", true, Boolean.class);
evaluate("3.0d >= 5.0d", false, Boolean.class);
evaluate("5.0d >= 3.0d", true, Boolean.class);
evaluate("5.0d <= 5.0d", true, Boolean.class);
evaluate("'abc' >= 'def'",false,Boolean.class);
evaluate("'def' >= 'abc'",true,Boolean.class);
evaluate("'abc' >= 'abc'",true,Boolean.class);
evaluate("5.0d >= 5.0d", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') >= new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') >= new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') >= new java.math.BigDecimal('3')", true, Boolean.class);
@ -227,11 +285,19 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("3L >= new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d >= new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d >= new java.math.BigDecimal('3.0')", true, Boolean.class);
evaluate("'abc' >= 'def'", false, Boolean.class);
evaluate("'def' >= 'abc'", true, Boolean.class);
evaluate("'abc' >= 'abc'", true, Boolean.class);
evaluate("3 GE 5", false, Boolean.class);
evaluate("5 gE 3", true, Boolean.class);
evaluate("6 Ge 6", true, Boolean.class);
evaluate("3L ge 5L", false, Boolean.class);
evaluate("5L ge 3L", true, Boolean.class);
evaluate("5L ge 5L", true, Boolean.class);
evaluate("3.0d ge 5.0d", false, Boolean.class);
evaluate("5.0d ge 3.0d", true, Boolean.class);
evaluate("5.0d ge 5.0d", true, Boolean.class);
evaluate("new java.math.BigDecimal('5') ge new java.math.BigDecimal('5')", true, Boolean.class);
evaluate("new java.math.BigDecimal('3') ge new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') ge new java.math.BigDecimal('3')", true, Boolean.class);
@ -242,41 +308,19 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("3L ge new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d ge new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d ge new java.math.BigDecimal('3.0')", true, Boolean.class);
evaluate("'abc' ge 'def'", false, Boolean.class);
evaluate("'def' ge 'abc'", true, Boolean.class);
evaluate("'abc' ge 'abc'", true, Boolean.class);
}
@Test
public void testGreaterThan() {
evaluate("3 > 5", false, Boolean.class);
evaluate("5 > 3", true, Boolean.class);
evaluate("3L > 5L", false, Boolean.class);
evaluate("5L > 3L", true, Boolean.class);
evaluate("3.0d > 5.0d", false, Boolean.class);
evaluate("5.0d > 3.0d", true, Boolean.class);
evaluate("'abc' > 'def'",false,Boolean.class);
evaluate("'def' > 'abc'",true,Boolean.class);
evaluate("new java.math.BigDecimal('3') > new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') > new java.math.BigDecimal('3')", true, Boolean.class);
evaluate("3 > new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('3') > 5", false, Boolean.class);
evaluate("3L > new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("3.0d > new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("3L > new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d > new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d > new java.math.BigDecimal('3.0')", false, Boolean.class);
public void testIntegerLiteral() {
evaluate("3", 3, Integer.class);
}
evaluate("3.0d gt 5.0d", false, Boolean.class);
evaluate("5.0d gT 3.0d", true, Boolean.class);
evaluate("'abc' Gt 'def'",false,Boolean.class);
evaluate("'def' GT 'abc'",true,Boolean.class);
evaluate("new java.math.BigDecimal('3') gt new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('5') gt new java.math.BigDecimal('3')", true, Boolean.class);
evaluate("3 gt new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("new java.math.BigDecimal('3') gt 5", false, Boolean.class);
evaluate("3L gt new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("3.0d gt new java.math.BigDecimal('5')", false, Boolean.class);
evaluate("3L gt new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d gt new java.math.BigDecimal('3.1')", false, Boolean.class);
evaluate("3.0d gt new java.math.BigDecimal('3.0')", false, Boolean.class);
@Test
public void testRealLiteral() {
evaluate("3.5", 3.5d, Double.class);
}
@Test
@ -527,10 +571,10 @@ public class OperatorTests extends AbstractExpressionTests {
@Test
public void testStrings() {
evaluate("'abc' == 'abc'",true,Boolean.class);
evaluate("'abc' == 'def'",false,Boolean.class);
evaluate("'abc' != 'abc'",false,Boolean.class);
evaluate("'abc' != 'def'",true,Boolean.class);
evaluate("'abc' == 'abc'", true, Boolean.class);
evaluate("'abc' == 'def'", false, Boolean.class);
evaluate("'abc' != 'abc'", false, Boolean.class);
evaluate("'abc' != 'def'", true, Boolean.class);
}
@Test
@ -544,25 +588,41 @@ public class OperatorTests extends AbstractExpressionTests {
evaluate("3L - 50L", -47L, Long.class);
}
// ---
private Operator getOperatorNode(SpelExpression e) {
SpelNode node = e.getAST();
return (Operator)findNode(node,Operator.class);
private Operator getOperatorNode(SpelExpression expr) {
SpelNode node = expr.getAST();
return findOperator(node);
}
private SpelNode findNode(SpelNode node, Class<Operator> clazz) {
if (clazz.isAssignableFrom(node.getClass())) {
return node;
private Operator findOperator(SpelNode node) {
if (node instanceof Operator) {
return (Operator) node;
}
int childCount = node.getChildCount();
for (int i=0;i<childCount;i++) {
SpelNode possible = findNode(node.getChild(i),clazz);
if (possible!=null) {
for (int i = 0; i < childCount; i++) {
Operator possible = findOperator(node.getChild(i));
if (possible != null) {
return possible;
}
}
return null;
}
public static class BaseComparable implements Comparable<BaseComparable> {
@Override
public int compareTo(BaseComparable other) {
return 0;
}
}
public static class SubComparable extends BaseComparable {
}
public static class OtherSubComparable extends BaseComparable {
}
}