SpelExpression consistently exposes EvaluationContext to compiled AST
Operator includes explicit support for Boolean comparisons now.
Issue: SPR-17229
(cherry picked from commit 51cee658d5)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -40,7 +40,7 @@ import org.springframework.util.ObjectUtils;
|
||||
public abstract class Operator extends SpelNodeImpl {
|
||||
|
||||
private final String operatorName;
|
||||
|
||||
|
||||
// The descriptors of the runtime operand values are used if the discovered declared
|
||||
// descriptors are not providing enough information (for example a generic type
|
||||
// whose accessors seem to only be returning 'Object' - the actual descriptors may
|
||||
@@ -70,7 +70,8 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
}
|
||||
|
||||
/**
|
||||
* String format for all operators is the same '(' [operand] [operator] [operand] ')'
|
||||
* String format for all operators is the same
|
||||
* {@code '(' [operand] [operator] [operand] ')'}.
|
||||
*/
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
@@ -100,8 +101,8 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
return (dc.areNumbers && dc.areCompatible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric comparison operators share very similar generated code, only differing in
|
||||
/**
|
||||
* Numeric comparison operators share very similar generated code, only differing in
|
||||
* two comparison instructions.
|
||||
*/
|
||||
protected void generateComparisonCode(MethodVisitor mv, CodeFlow cf, int compInstruction1, int compInstruction2) {
|
||||
@@ -113,14 +114,14 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
|
||||
leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
char targetType = dc.compatibleType; // CodeFlow.toPrimitiveTargetDesc(leftDesc);
|
||||
|
||||
|
||||
cf.enterCompilationScope();
|
||||
getLeftOperand().generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
if (unboxLeft) {
|
||||
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
|
||||
}
|
||||
|
||||
|
||||
cf.enterCompilationScope();
|
||||
getRightOperand().generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
@@ -136,11 +137,11 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
mv.visitJumpInsn(compInstruction1, elseTarget);
|
||||
}
|
||||
else if (targetType == 'F') {
|
||||
mv.visitInsn(FCMPG);
|
||||
mv.visitInsn(FCMPG);
|
||||
mv.visitJumpInsn(compInstruction1, elseTarget);
|
||||
}
|
||||
else if (targetType == 'J') {
|
||||
mv.visitInsn(LCMP);
|
||||
mv.visitInsn(LCMP);
|
||||
mv.visitJumpInsn(compInstruction1, elseTarget);
|
||||
}
|
||||
else if (targetType == 'I') {
|
||||
@@ -212,6 +213,10 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
return left.toString().equals(right.toString());
|
||||
}
|
||||
|
||||
if (left instanceof Boolean && right instanceof Boolean) {
|
||||
return left.equals(right);
|
||||
}
|
||||
|
||||
if (ObjectUtils.nullSafeEquals(left, right)) {
|
||||
return true;
|
||||
}
|
||||
@@ -225,7 +230,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A descriptor comparison encapsulates the result of comparing descriptor
|
||||
@@ -248,7 +253,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
this.areCompatible = areCompatible;
|
||||
this.compatibleType = compatibleType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an object that indicates whether the input descriptors are compatible.
|
||||
* <p>A declared descriptor is what could statically be determined (e.g. from looking
|
||||
@@ -271,7 +276,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
|
||||
boolean leftNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(ld);
|
||||
boolean rightNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(rd);
|
||||
|
||||
|
||||
// If the declared descriptors aren't providing the information, try the actual descriptors
|
||||
if (!leftNumeric && !ObjectUtils.nullSafeEquals(ld, leftActualDescriptor)) {
|
||||
ld = leftActualDescriptor;
|
||||
@@ -281,7 +286,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
rd = rightActualDescriptor;
|
||||
rightNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(rd);
|
||||
}
|
||||
|
||||
|
||||
if (leftNumeric && rightNumeric) {
|
||||
if (CodeFlow.areBoxingCompatible(ld, rd)) {
|
||||
return new DescriptorComparison(true, true, CodeFlow.toPrimitiveTargetDesc(ld));
|
||||
@@ -292,7 +297,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
}
|
||||
else {
|
||||
return DescriptorComparison.NOT_NUMBERS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -114,10 +114,8 @@ public class SpelExpression implements Expression {
|
||||
public Object getValue() throws EvaluationException {
|
||||
if (this.compiledAst != null) {
|
||||
try {
|
||||
TypedValue contextRoot =
|
||||
(this.evaluationContext != null ? this.evaluationContext.getRootObject() : null);
|
||||
return this.compiledAst.getValue(
|
||||
(contextRoot != null ? contextRoot.getValue() : null), this.evaluationContext);
|
||||
EvaluationContext context = getEvaluationContext();
|
||||
return this.compiledAst.getValue(context.getRootObject().getValue(), context);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// If running in mixed mode, revert to interpreted
|
||||
@@ -143,10 +141,8 @@ public class SpelExpression implements Expression {
|
||||
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
|
||||
if (this.compiledAst != null) {
|
||||
try {
|
||||
TypedValue contextRoot =
|
||||
(this.evaluationContext != null ? this.evaluationContext.getRootObject() : null);
|
||||
Object result = this.compiledAst.getValue(
|
||||
(contextRoot != null ? contextRoot.getValue() : null), this.evaluationContext);
|
||||
EvaluationContext context = getEvaluationContext();
|
||||
Object result = this.compiledAst.getValue(context.getRootObject().getValue(), context);
|
||||
if (expectedResultType == null) {
|
||||
return (T) result;
|
||||
}
|
||||
@@ -179,7 +175,7 @@ public class SpelExpression implements Expression {
|
||||
public Object getValue(Object rootObject) throws EvaluationException {
|
||||
if (this.compiledAst != null) {
|
||||
try {
|
||||
return this.compiledAst.getValue(rootObject, evaluationContext);
|
||||
return this.compiledAst.getValue(rootObject, getEvaluationContext());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// If running in mixed mode, revert to interpreted
|
||||
@@ -206,7 +202,7 @@ public class SpelExpression implements Expression {
|
||||
public <T> T getValue(Object rootObject, Class<T> expectedResultType) throws EvaluationException {
|
||||
if (this.compiledAst != null) {
|
||||
try {
|
||||
Object result = this.compiledAst.getValue(rootObject, null);
|
||||
Object result = this.compiledAst.getValue(rootObject, getEvaluationContext());
|
||||
if (expectedResultType == null) {
|
||||
return (T)result;
|
||||
}
|
||||
@@ -242,8 +238,7 @@ public class SpelExpression implements Expression {
|
||||
|
||||
if (this.compiledAst != null) {
|
||||
try {
|
||||
TypedValue contextRoot = context.getRootObject();
|
||||
return this.compiledAst.getValue(contextRoot.getValue(), context);
|
||||
return this.compiledAst.getValue(context.getRootObject().getValue(), context);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// If running in mixed mode, revert to interpreted
|
||||
@@ -271,8 +266,7 @@ public class SpelExpression implements Expression {
|
||||
|
||||
if (this.compiledAst != null) {
|
||||
try {
|
||||
TypedValue contextRoot = context.getRootObject();
|
||||
Object result = this.compiledAst.getValue(contextRoot.getValue(), context);
|
||||
Object result = this.compiledAst.getValue(context.getRootObject().getValue(), context);
|
||||
if (expectedResultType != null) {
|
||||
return ExpressionUtils.convertTypedValue(context, new TypedValue(result), expectedResultType);
|
||||
}
|
||||
@@ -305,7 +299,7 @@ public class SpelExpression implements Expression {
|
||||
|
||||
if (this.compiledAst != null) {
|
||||
try {
|
||||
return this.compiledAst.getValue(rootObject,context);
|
||||
return this.compiledAst.getValue(rootObject, context);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// If running in mixed mode, revert to interpreted
|
||||
|
||||
Reference in New Issue
Block a user