parent
d178eafc11
commit
fab9abd7fe
|
@ -24,7 +24,6 @@ import org.springframework.asm.MethodVisitor;
|
|||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.CodeFlow;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.NumberUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public class StandardTypeComparator implements TypeComparator {
|
|||
return true;
|
||||
}
|
||||
if (left instanceof Comparable && right instanceof Comparable) {
|
||||
Class<?> ancestor = ClassUtils.determineCommonAncestor(left.getClass(), right.getClass());
|
||||
Class<?> ancestor = ClassUtils.determineCommonAncestor(left.getClass(), right.getClass());
|
||||
return ancestor != null && Comparable.class.isAssignableFrom(ancestor);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.TypeComparator;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test construction of arrays.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class AlternativeComparatorTests {
|
||||
private ExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
// A silly comparator declaring everything to be equal
|
||||
private TypeComparator customComparator = new TypeComparator() {
|
||||
@Override
|
||||
public boolean canCompare(@Nullable Object firstObject, @Nullable Object secondObject) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(@Nullable Object firstObject, @Nullable Object secondObject) throws EvaluationException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@Test
|
||||
public void customComparatorWorksWithEquality() {
|
||||
final StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||
ctx.setTypeComparator(customComparator);
|
||||
|
||||
Expression expr = parser.parseExpression("'1' == 1");
|
||||
|
||||
assertEquals(true, expr.getValue(ctx, Boolean.class));
|
||||
|
||||
}
|
||||
}
|
|
@ -21,8 +21,13 @@ import java.math.BigDecimal;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.TypeComparator;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeComparator;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
@ -32,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
* @author Andy Clement
|
||||
* @author Giovanni Dall'Oglio Risso
|
||||
*/
|
||||
class DefaultComparatorUnitTests {
|
||||
public class ComparatorTests {
|
||||
|
||||
@Test
|
||||
void testPrimitives() throws EvaluationException {
|
||||
|
@ -120,4 +125,30 @@ class DefaultComparatorUnitTests {
|
|||
assertThat(comparator.canCompare(String.class,3)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customComparatorWorksWithEquality() {
|
||||
final StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||
ctx.setTypeComparator(customComparator);
|
||||
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
Expression expr = parser.parseExpression("'1' == 1");
|
||||
|
||||
assertThat(expr.getValue(ctx, Boolean.class)).isTrue();
|
||||
|
||||
}
|
||||
|
||||
// A silly comparator declaring everything to be equal
|
||||
private TypeComparator customComparator = new TypeComparator() {
|
||||
@Override
|
||||
public boolean canCompare(@Nullable Object firstObject, @Nullable Object secondObject) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(@Nullable Object firstObject, @Nullable Object secondObject) throws EvaluationException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -58,7 +58,9 @@ class OperatorTests extends AbstractExpressionTests {
|
|||
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("new org.springframework.expression.spel.OperatorTests$SubComparable(0) == new org.springframework.expression.spel.OperatorTests$OtherSubComparable(0)", true, Boolean.class);
|
||||
evaluate("new org.springframework.expression.spel.OperatorTests$SubComparable(1) < new org.springframework.expression.spel.OperatorTests$OtherSubComparable(2)", true, Boolean.class);
|
||||
evaluate("new org.springframework.expression.spel.OperatorTests$SubComparable(2) > new org.springframework.expression.spel.OperatorTests$OtherSubComparable(1)", true, Boolean.class);
|
||||
|
||||
evaluate("3 eq 5", false, Boolean.class);
|
||||
evaluate("5 eQ 3", false, Boolean.class);
|
||||
|
@ -621,18 +623,40 @@ class OperatorTests extends AbstractExpressionTests {
|
|||
|
||||
public static class BaseComparable implements Comparable<BaseComparable> {
|
||||
|
||||
private int id;
|
||||
|
||||
public BaseComparable() {
|
||||
this.id = 0;
|
||||
}
|
||||
|
||||
public BaseComparable(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(BaseComparable other) {
|
||||
return 0;
|
||||
return this.id - other.id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SubComparable extends BaseComparable {
|
||||
public SubComparable() {
|
||||
}
|
||||
|
||||
public SubComparable(int id) {
|
||||
super(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class OtherSubComparable extends BaseComparable {
|
||||
public OtherSubComparable() {
|
||||
}
|
||||
|
||||
public OtherSubComparable(int id) {
|
||||
super(id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright 2002-2021 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.TypeComparator;
|
||||
import org.springframework.expression.spel.support.StandardTypeComparator;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for type comparison
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Giovanni Dall'Oglio Risso
|
||||
*/
|
||||
public class StandardTypeComparatorTests {
|
||||
|
||||
@Test
|
||||
void testPrimitives() throws EvaluationException {
|
||||
TypeComparator comparator = new StandardTypeComparator();
|
||||
// primitive int
|
||||
assertThat(comparator.compare(1, 2)).isNegative();
|
||||
assertThat(comparator.compare(1, 1)).isZero();
|
||||
assertThat(comparator.compare(2, 1)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1.0d, 2)).isNegative();
|
||||
assertThat(comparator.compare(1.0d, 1)).isZero();
|
||||
assertThat(comparator.compare(2.0d, 1)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1.0f, 2)).isNegative();
|
||||
assertThat(comparator.compare(1.0f, 1)).isZero();
|
||||
assertThat(comparator.compare(2.0f, 1)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1L, 2)).isNegative();
|
||||
assertThat(comparator.compare(1L, 1)).isZero();
|
||||
assertThat(comparator.compare(2L, 1)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1, 2L)).isNegative();
|
||||
assertThat(comparator.compare(1, 1L)).isZero();
|
||||
assertThat(comparator.compare(2, 1L)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1L, 2L)).isNegative();
|
||||
assertThat(comparator.compare(1L, 1L)).isZero();
|
||||
assertThat(comparator.compare(2L, 1L)).isPositive();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNonPrimitiveNumbers() throws EvaluationException {
|
||||
TypeComparator comparator = new StandardTypeComparator();
|
||||
|
||||
BigDecimal bdOne = new BigDecimal("1");
|
||||
BigDecimal bdTwo = new BigDecimal("2");
|
||||
|
||||
assertThat(comparator.compare(bdOne, bdTwo)).isNegative();
|
||||
assertThat(comparator.compare(bdOne, new BigDecimal("1"))).isZero();
|
||||
assertThat(comparator.compare(bdTwo, bdOne)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1, bdTwo)).isNegative();
|
||||
assertThat(comparator.compare(1, bdOne)).isZero();
|
||||
assertThat(comparator.compare(2, bdOne)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1.0d, bdTwo)).isNegative();
|
||||
assertThat(comparator.compare(1.0d, bdOne)).isZero();
|
||||
assertThat(comparator.compare(2.0d, bdOne)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1.0f, bdTwo)).isNegative();
|
||||
assertThat(comparator.compare(1.0f, bdOne)).isZero();
|
||||
assertThat(comparator.compare(2.0f, bdOne)).isPositive();
|
||||
|
||||
assertThat(comparator.compare(1L, bdTwo)).isNegative();
|
||||
assertThat(comparator.compare(1L, bdOne)).isZero();
|
||||
assertThat(comparator.compare(2L, bdOne)).isPositive();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNulls() throws EvaluationException {
|
||||
TypeComparator comparator = new StandardTypeComparator();
|
||||
assertThat(comparator.compare(null, "abc")).isNegative();
|
||||
assertThat(comparator.compare(null, null)).isZero();
|
||||
assertThat(comparator.compare("abc", null)).isPositive();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testObjects() throws EvaluationException {
|
||||
TypeComparator comparator = new StandardTypeComparator();
|
||||
assertThat(comparator.compare("a", "a")).isZero();
|
||||
assertThat(comparator.compare("a", "b")).isNegative();
|
||||
assertThat(comparator.compare("b", "a")).isPositive();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCanCompare() throws EvaluationException {
|
||||
TypeComparator comparator = new StandardTypeComparator();
|
||||
assertThat(comparator.canCompare(null, 1)).isTrue();
|
||||
assertThat(comparator.canCompare(1, null)).isTrue();
|
||||
|
||||
assertThat(comparator.canCompare(2, 1)).isTrue();
|
||||
assertThat(comparator.canCompare("abc", "def")).isTrue();
|
||||
assertThat(comparator.canCompare("abc", 3)).isFalse();
|
||||
assertThat(comparator.canCompare(String.class, 3)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUseCustomComparator() {
|
||||
TypeComparator comparator = new StandardTypeComparator();
|
||||
ComparableType t1 = new ComparableType(1);
|
||||
ComparableType t2 = new ComparableType(2);
|
||||
|
||||
assertThat(comparator.canCompare(t1, 2)).isFalse();
|
||||
assertThat(comparator.canCompare(t1, t2)).isTrue();
|
||||
assertThat(comparator.compare(t1, t1)).isZero();
|
||||
assertThat(comparator.compare(t1, t2)).isNegative();
|
||||
assertThat(comparator.compare(t2, t1)).isPositive();
|
||||
}
|
||||
|
||||
static class ComparableType implements Comparable<ComparableType> {
|
||||
|
||||
private final int id;
|
||||
|
||||
public ComparableType(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull ComparableType other) {
|
||||
return this.id - other.id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1052,8 +1052,9 @@ The Spring Expression Language supports the following kinds of operators:
|
|||
==== Relational Operators
|
||||
|
||||
The relational operators (equal, not equal, less than, less than or equal, greater than,
|
||||
and greater than or equal) are supported by using standard operator notation. The
|
||||
following listing shows a few examples of operators:
|
||||
and greater than or equal) are supported by using standard operator notation.
|
||||
These operators work on `Number` types as well as types implementing `Comparable`.
|
||||
The following listing shows a few examples of operators:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
|
@ -1066,6 +1067,9 @@ following listing shows a few examples of operators:
|
|||
|
||||
// evaluates to true
|
||||
boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
|
||||
|
||||
// uses CustomValue:::compareTo
|
||||
boolean trueValue = parser.parseExpression("new CustomValue(1) < new CustomValue(2)").getValue(Boolean.class);
|
||||
----
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
|
@ -1078,6 +1082,9 @@ following listing shows a few examples of operators:
|
|||
|
||||
// evaluates to true
|
||||
val trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean::class.java)
|
||||
|
||||
// uses CustomValue:::compareTo
|
||||
val trueValue = parser.parseExpression("new CustomValue(1) < new CustomValue(2)").getValue(Boolean::class.java);
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
|
|
Loading…
Reference in New Issue