Apply "instanceof pattern matching" in spring-expression

This commit also applies additional clean-up tasks such as the following.

- final fields

This commit also makes use of java.lang.String.repeat(int) in OptMultiply.

This has only been applied to `src/main/java`.
This commit is contained in:
Sam Brannen
2021-10-14 19:46:21 +02:00
parent cb17441780
commit 4e6ef82d8f
23 changed files with 151 additions and 206 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -85,10 +85,9 @@ public class TypedValue {
if (this == other) { if (this == other) {
return true; return true;
} }
if (!(other instanceof TypedValue)) { if (!(other instanceof TypedValue otherTv)) {
return false; return false;
} }
TypedValue otherTv = (TypedValue) other;
// Avoid TypeDescriptor initialization if not necessary // Avoid TypeDescriptor initialization if not necessary
return (ObjectUtils.nullSafeEquals(this.value, otherTv.value) && return (ObjectUtils.nullSafeEquals(this.value, otherTv.value) &&
((this.typeDescriptor == null && otherTv.typeDescriptor == null) || ((this.typeDescriptor == null && otherTv.typeDescriptor == null) ||

View File

@@ -136,8 +136,8 @@ public class ConstructorReference extends SpelNodeImpl {
if (ex.getCause() instanceof InvocationTargetException) { if (ex.getCause() instanceof InvocationTargetException) {
// User exception was the root cause - exit now // User exception was the root cause - exit now
Throwable rootCause = ex.getCause().getCause(); Throwable rootCause = ex.getCause().getCause();
if (rootCause instanceof RuntimeException) { if (rootCause instanceof RuntimeException runtimeException) {
throw (RuntimeException) rootCause; throw runtimeException;
} }
else { else {
String typeName = (String) this.children[0].getValueInternal(state).getValue(); String typeName = (String) this.children[0].getValueInternal(state).getValue();
@@ -158,9 +158,9 @@ public class ConstructorReference extends SpelNodeImpl {
executorToUse = findExecutorForConstructor(typeName, argumentTypes, state); executorToUse = findExecutorForConstructor(typeName, argumentTypes, state);
try { try {
this.cachedExecutor = executorToUse; this.cachedExecutor = executorToUse;
if (executorToUse instanceof ReflectiveConstructorExecutor) { if (executorToUse instanceof ReflectiveConstructorExecutor reflectiveConstructorExecutor) {
this.exitTypeDescriptor = CodeFlow.toDescriptor( this.exitTypeDescriptor = CodeFlow.toDescriptor(
((ReflectiveConstructorExecutor) executorToUse).getConstructor().getDeclaringClass()); reflectiveConstructorExecutor.getConstructor().getDeclaringClass());
} }
return executorToUse.execute(state.getEvaluationContext(), arguments); return executorToUse.execute(state.getEvaluationContext(), arguments);
@@ -228,14 +228,13 @@ public class ConstructorReference extends SpelNodeImpl {
private TypedValue createArray(ExpressionState state) throws EvaluationException { private TypedValue createArray(ExpressionState state) throws EvaluationException {
// First child gives us the array type which will either be a primitive or reference type // First child gives us the array type which will either be a primitive or reference type
Object intendedArrayType = getChild(0).getValue(state); Object intendedArrayType = getChild(0).getValue(state);
if (!(intendedArrayType instanceof String)) { if (!(intendedArrayType instanceof String type)) {
throw new SpelEvaluationException(getChild(0).getStartPosition(), throw new SpelEvaluationException(getChild(0).getStartPosition(),
SpelMessage.TYPE_NAME_EXPECTED_FOR_ARRAY_CONSTRUCTION, SpelMessage.TYPE_NAME_EXPECTED_FOR_ARRAY_CONSTRUCTION,
FormatHelper.formatClassNameForMessage( FormatHelper.formatClassNameForMessage(
intendedArrayType != null ? intendedArrayType.getClass() : null)); intendedArrayType != null ? intendedArrayType.getClass() : null));
} }
String type = (String) intendedArrayType;
Class<?> componentType; Class<?> componentType;
TypeCode arrayTypeCode = TypeCode.forName(type); TypeCode arrayTypeCode = TypeCode.forName(type);
if (arrayTypeCode == TypeCode.OBJECT) { if (arrayTypeCode == TypeCode.OBJECT) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2020 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -50,6 +50,7 @@ import org.springframework.util.ReflectionUtils;
* @author Andy Clement * @author Andy Clement
* @author Phillip Webb * @author Phillip Webb
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Sam Brannen
* @since 3.0 * @since 3.0
*/ */
// TODO support multidimensional arrays // TODO support multidimensional arrays
@@ -121,8 +122,7 @@ public class Indexer extends SpelNodeImpl {
Object index; Object index;
// This first part of the if clause prevents a 'double dereference' of the property (SPR-5847) // This first part of the if clause prevents a 'double dereference' of the property (SPR-5847)
if (target instanceof Map && (this.children[0] instanceof PropertyOrFieldReference)) { if (target instanceof Map && (this.children[0] instanceof PropertyOrFieldReference reference)) {
PropertyOrFieldReference reference = (PropertyOrFieldReference) this.children[0];
index = reference.getName(); index = reference.getName();
indexValue = new TypedValue(index); indexValue = new TypedValue(index);
} }
@@ -148,13 +148,13 @@ public class Indexer extends SpelNodeImpl {
Assert.state(targetDescriptor != null, "No type descriptor"); Assert.state(targetDescriptor != null, "No type descriptor");
// Indexing into a Map // Indexing into a Map
if (target instanceof Map) { if (target instanceof Map<?, ?> map) {
Object key = index; Object key = index;
if (targetDescriptor.getMapKeyTypeDescriptor() != null) { if (targetDescriptor.getMapKeyTypeDescriptor() != null) {
key = state.convertValue(key, targetDescriptor.getMapKeyTypeDescriptor()); key = state.convertValue(key, targetDescriptor.getMapKeyTypeDescriptor());
} }
this.indexedType = IndexedType.MAP; this.indexedType = IndexedType.MAP;
return new MapIndexingValueRef(state.getTypeConverter(), (Map<?, ?>) target, key, targetDescriptor); return new MapIndexingValueRef(state.getTypeConverter(), map, key, targetDescriptor);
} }
// If the object is something that looks indexable by an integer, // If the object is something that looks indexable by an integer,
@@ -275,8 +275,7 @@ public class Indexer extends SpelNodeImpl {
mv.visitTypeInsn(CHECKCAST, "java/util/Map"); mv.visitTypeInsn(CHECKCAST, "java/util/Map");
// Special case when the key is an unquoted string literal that will be parsed as // Special case when the key is an unquoted string literal that will be parsed as
// a property/field reference // a property/field reference
if ((this.children[0] instanceof PropertyOrFieldReference)) { if ((this.children[0] instanceof PropertyOrFieldReference reference)) {
PropertyOrFieldReference reference = (PropertyOrFieldReference) this.children[0];
String mapKeyName = reference.getName(); String mapKeyName = reference.getName();
mv.visitLdcInsn(mapKeyName); mv.visitLdcInsn(mapKeyName);
} }
@@ -306,9 +305,9 @@ public class Indexer extends SpelNodeImpl {
} }
} }
if (member instanceof Method) { if (member instanceof Method method) {
mv.visitMethodInsn((isStatic? INVOKESTATIC : INVOKEVIRTUAL), classDesc, member.getName(), mv.visitMethodInsn((isStatic? INVOKESTATIC : INVOKEVIRTUAL), classDesc, member.getName(),
CodeFlow.createSignatureDescriptor((Method) member), false); CodeFlow.createSignatureDescriptor(method), false);
} }
else { else {
mv.visitFieldInsn((isStatic ? GETSTATIC : GETFIELD), classDesc, member.getName(), mv.visitFieldInsn((isStatic ? GETSTATIC : GETFIELD), classDesc, member.getName(),
@@ -572,19 +571,17 @@ public class Indexer extends SpelNodeImpl {
targetObjectRuntimeClass, this.evaluationContext.getPropertyAccessors()); targetObjectRuntimeClass, this.evaluationContext.getPropertyAccessors());
for (PropertyAccessor accessor : accessorsToTry) { for (PropertyAccessor accessor : accessorsToTry) {
if (accessor.canRead(this.evaluationContext, this.targetObject, this.name)) { if (accessor.canRead(this.evaluationContext, this.targetObject, this.name)) {
if (accessor instanceof ReflectivePropertyAccessor) { if (accessor instanceof ReflectivePropertyAccessor reflectivePropertyAccessor) {
accessor = ((ReflectivePropertyAccessor) accessor).createOptimalAccessor( accessor = reflectivePropertyAccessor.createOptimalAccessor(
this.evaluationContext, this.targetObject, this.name); this.evaluationContext, this.targetObject, this.name);
} }
Indexer.this.cachedReadAccessor = accessor; Indexer.this.cachedReadAccessor = accessor;
Indexer.this.cachedReadName = this.name; Indexer.this.cachedReadName = this.name;
Indexer.this.cachedReadTargetType = targetObjectRuntimeClass; Indexer.this.cachedReadTargetType = targetObjectRuntimeClass;
if (accessor instanceof ReflectivePropertyAccessor.OptimalPropertyAccessor) { if (accessor instanceof ReflectivePropertyAccessor.OptimalPropertyAccessor optimalAccessor) {
ReflectivePropertyAccessor.OptimalPropertyAccessor optimalAccessor =
(ReflectivePropertyAccessor.OptimalPropertyAccessor) accessor;
Member member = optimalAccessor.member; Member member = optimalAccessor.member;
Indexer.this.exitTypeDescriptor = CodeFlow.toDescriptor(member instanceof Method ? Indexer.this.exitTypeDescriptor = CodeFlow.toDescriptor(member instanceof Method method ?
((Method) member).getReturnType() : ((Field) member).getType()); method.getReturnType() : ((Field) member).getType());
} }
return accessor.read(this.evaluationContext, this.targetObject, this.name); return accessor.read(this.evaluationContext, this.targetObject, this.name);
} }
@@ -665,8 +662,8 @@ public class Indexer extends SpelNodeImpl {
@Override @Override
public TypedValue getValue() { public TypedValue getValue() {
growCollectionIfNecessary(); growCollectionIfNecessary();
if (this.collection instanceof List) { if (this.collection instanceof List list) {
Object o = ((List) this.collection).get(this.index); Object o = list.get(this.index);
exitTypeDescriptor = CodeFlow.toDescriptor(Object.class); exitTypeDescriptor = CodeFlow.toDescriptor(Object.class);
return new TypedValue(o, this.collectionEntryDescriptor.elementTypeDescriptor(o)); return new TypedValue(o, this.collectionEntryDescriptor.elementTypeDescriptor(o));
} }
@@ -683,8 +680,7 @@ public class Indexer extends SpelNodeImpl {
@Override @Override
public void setValue(@Nullable Object newValue) { public void setValue(@Nullable Object newValue) {
growCollectionIfNecessary(); growCollectionIfNecessary();
if (this.collection instanceof List) { if (this.collection instanceof List list) {
List list = (List) this.collection;
if (this.collectionEntryDescriptor.getElementTypeDescriptor() != null) { if (this.collectionEntryDescriptor.getElementTypeDescriptor() != null) {
newValue = this.typeConverter.convertValue(newValue, TypeDescriptor.forObject(newValue), newValue = this.typeConverter.convertValue(newValue, TypeDescriptor.forObject(newValue),
this.collectionEntryDescriptor.getElementTypeDescriptor()); this.collectionEntryDescriptor.getElementTypeDescriptor());

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.util.Assert;
* Represent a list in an expression, e.g. '{1,2,3}' * Represent a list in an expression, e.g. '{1,2,3}'
* *
* @author Andy Clement * @author Andy Clement
* @author Sam Brannen
* @since 3.0.4 * @since 3.0.4
*/ */
public class InlineList extends SpelNodeImpl { public class InlineList extends SpelNodeImpl {
@@ -59,8 +60,7 @@ public class InlineList extends SpelNodeImpl {
for (int c = 0, max = getChildCount(); c < max; c++) { for (int c = 0, max = getChildCount(); c < max; c++) {
SpelNode child = getChild(c); SpelNode child = getChild(c);
if (!(child instanceof Literal)) { if (!(child instanceof Literal)) {
if (child instanceof InlineList) { if (child instanceof InlineList inlineList) {
InlineList inlineList = (InlineList) child;
if (!inlineList.isConstant()) { if (!inlineList.isConstant()) {
isConstant = false; isConstant = false;
} }
@@ -75,11 +75,11 @@ public class InlineList extends SpelNodeImpl {
int childcount = getChildCount(); int childcount = getChildCount();
for (int c = 0; c < childcount; c++) { for (int c = 0; c < childcount; c++) {
SpelNode child = getChild(c); SpelNode child = getChild(c);
if ((child instanceof Literal)) { if (child instanceof Literal literal) {
constantList.add(((Literal) child).getLiteralValue().getValue()); constantList.add(literal.getLiteralValue().getValue());
} }
else if (child instanceof InlineList) { else if (child instanceof InlineList inlineList) {
constantList.add(((InlineList) child).getConstantValue()); constantList.add(inlineList.getConstantValue());
} }
} }
this.constant = new TypedValue(Collections.unmodifiableList(constantList)); this.constant = new TypedValue(Collections.unmodifiableList(constantList));
@@ -164,8 +164,8 @@ public class InlineList extends SpelNodeImpl {
// The children might be further lists if they are not constants. In this // The children might be further lists if they are not constants. In this
// situation do not call back into generateCode() because it will register another clinit adder. // situation do not call back into generateCode() because it will register another clinit adder.
// Instead, directly build the list here: // Instead, directly build the list here:
if (this.children[c] instanceof InlineList) { if (this.children[c] instanceof InlineList inlineList) {
((InlineList)this.children[c]).generateClinitCode(clazzname, constantFieldName, mv, codeflow, true); inlineList.generateClinitCode(clazzname, constantFieldName, mv, codeflow, true);
} }
else { else {
this.children[c].generateCode(mv, codeflow); this.children[c].generateCode(mv, codeflow);

View File

@@ -31,6 +31,7 @@ import org.springframework.util.Assert;
* Represent a map in an expression, e.g. '{name:'foo',age:12}' * Represent a map in an expression, e.g. '{name:'foo',age:12}'
* *
* @author Andy Clement * @author Andy Clement
* @author Sam Brannen
* @since 4.1 * @since 4.1
*/ */
public class InlineMap extends SpelNodeImpl { public class InlineMap extends SpelNodeImpl {
@@ -56,15 +57,13 @@ public class InlineMap extends SpelNodeImpl {
for (int c = 0, max = getChildCount(); c < max; c++) { for (int c = 0, max = getChildCount(); c < max; c++) {
SpelNode child = getChild(c); SpelNode child = getChild(c);
if (!(child instanceof Literal)) { if (!(child instanceof Literal)) {
if (child instanceof InlineList) { if (child instanceof InlineList inlineList) {
InlineList inlineList = (InlineList) child;
if (!inlineList.isConstant()) { if (!inlineList.isConstant()) {
isConstant = false; isConstant = false;
break; break;
} }
} }
else if (child instanceof InlineMap) { else if (child instanceof InlineMap inlineMap) {
InlineMap inlineMap = (InlineMap) child;
if (!inlineMap.isConstant()) { if (!inlineMap.isConstant()) {
isConstant = false; isConstant = false;
break; break;
@@ -84,23 +83,23 @@ public class InlineMap extends SpelNodeImpl {
SpelNode valueChild = getChild(c); SpelNode valueChild = getChild(c);
Object key = null; Object key = null;
Object value = null; Object value = null;
if (keyChild instanceof Literal) { if (keyChild instanceof Literal literal) {
key = ((Literal) keyChild).getLiteralValue().getValue(); key = literal.getLiteralValue().getValue();
} }
else if (keyChild instanceof PropertyOrFieldReference) { else if (keyChild instanceof PropertyOrFieldReference propertyOrFieldReference) {
key = ((PropertyOrFieldReference) keyChild).getName(); key = propertyOrFieldReference.getName();
} }
else { else {
return; return;
} }
if (valueChild instanceof Literal) { if (valueChild instanceof Literal literal) {
value = ((Literal) valueChild).getLiteralValue().getValue(); value = literal.getLiteralValue().getValue();
} }
else if (valueChild instanceof InlineList) { else if (valueChild instanceof InlineList inlineList) {
value = ((InlineList) valueChild).getConstantValue(); value = inlineList.getConstantValue();
} }
else if (valueChild instanceof InlineMap) { else if (valueChild instanceof InlineMap inlineMap) {
value = ((InlineMap) valueChild).getConstantValue(); value = inlineMap.getConstantValue();
} }
constantMap.put(key, value); constantMap.put(key, value);
} }
@@ -120,8 +119,7 @@ public class InlineMap extends SpelNodeImpl {
// TODO allow for key being PropertyOrFieldReference like Indexer on maps // TODO allow for key being PropertyOrFieldReference like Indexer on maps
SpelNode keyChild = getChild(c++); SpelNode keyChild = getChild(c++);
Object key = null; Object key = null;
if (keyChild instanceof PropertyOrFieldReference) { if (keyChild instanceof PropertyOrFieldReference reference) {
PropertyOrFieldReference reference = (PropertyOrFieldReference) keyChild;
key = reference.getName(); key = reference.getName();
} }
else { else {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.util.Assert;
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso * @author Giovanni Dall'Oglio Risso
* @author Sam Brannen
* @since 3.2 * @since 3.2
*/ */
public class OpDec extends Operator { public class OpDec extends Operator {
@@ -60,10 +61,9 @@ public class OpDec extends Operator {
TypedValue returnValue = operandTypedValue; TypedValue returnValue = operandTypedValue;
TypedValue newValue = null; TypedValue newValue = null;
if (operandValue instanceof Number) { if (operandValue instanceof Number op1) {
Number op1 = (Number) operandValue; if (op1 instanceof BigDecimal bigDecimal) {
if (op1 instanceof BigDecimal) { newValue = new TypedValue(bigDecimal.subtract(BigDecimal.ONE), operandTypedValue.getTypeDescriptor());
newValue = new TypedValue(((BigDecimal) op1).subtract(BigDecimal.ONE), operandTypedValue.getTypeDescriptor());
} }
else if (op1 instanceof Double) { else if (op1 instanceof Double) {
newValue = new TypedValue(op1.doubleValue() - 1.0d, operandTypedValue.getTypeDescriptor()); newValue = new TypedValue(op1.doubleValue() - 1.0d, operandTypedValue.getTypeDescriptor());
@@ -71,8 +71,8 @@ public class OpDec extends Operator {
else if (op1 instanceof Float) { else if (op1 instanceof Float) {
newValue = new TypedValue(op1.floatValue() - 1.0f, operandTypedValue.getTypeDescriptor()); newValue = new TypedValue(op1.floatValue() - 1.0f, operandTypedValue.getTypeDescriptor());
} }
else if (op1 instanceof BigInteger) { else if (op1 instanceof BigInteger bigInteger) {
newValue = new TypedValue(((BigInteger) op1).subtract(BigInteger.ONE), operandTypedValue.getTypeDescriptor()); newValue = new TypedValue(bigInteger.subtract(BigInteger.ONE), operandTypedValue.getTypeDescriptor());
} }
else if (op1 instanceof Long) { else if (op1 instanceof Long) {
newValue = new TypedValue(op1.longValue() - 1L, operandTypedValue.getTypeDescriptor()); newValue = new TypedValue(op1.longValue() - 1L, operandTypedValue.getTypeDescriptor());

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ import org.springframework.util.NumberUtils;
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso * @author Giovanni Dall'Oglio Risso
* @author Sam Brannen
* @since 3.0 * @since 3.0
*/ */
public class OpDivide extends Operator { public class OpDivide extends Operator {
@@ -49,10 +50,7 @@ public class OpDivide extends Operator {
Object leftOperand = getLeftOperand().getValueInternal(state).getValue(); Object leftOperand = getLeftOperand().getValueInternal(state).getValue();
Object rightOperand = getRightOperand().getValueInternal(state).getValue(); Object rightOperand = getRightOperand().getValueInternal(state).getValue();
if (leftOperand instanceof Number && rightOperand instanceof Number) { if (leftOperand instanceof Number leftNumber && rightOperand instanceof Number rightNumber) {
Number leftNumber = (Number) leftOperand;
Number rightNumber = (Number) rightOperand;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -50,10 +50,7 @@ public class OpGE extends Operator {
this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left); this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right); this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
if (left instanceof Number && right instanceof Number) { if (left instanceof Number leftNumber && right instanceof Number rightNumber) {
Number leftNumber = (Number) left;
Number rightNumber = (Number) right;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -50,10 +50,7 @@ public class OpGT extends Operator {
this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left); this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right); this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
if (left instanceof Number && right instanceof Number) { if (left instanceof Number leftNumber && right instanceof Number rightNumber) {
Number leftNumber = (Number) left;
Number rightNumber = (Number) right;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.util.Assert;
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso * @author Giovanni Dall'Oglio Risso
* @author Sam Brannen
* @since 3.2 * @since 3.2
*/ */
public class OpInc extends Operator { public class OpInc extends Operator {
@@ -58,10 +59,9 @@ public class OpInc extends Operator {
TypedValue returnValue = typedValue; TypedValue returnValue = typedValue;
TypedValue newValue = null; TypedValue newValue = null;
if (value instanceof Number) { if (value instanceof Number op1) {
Number op1 = (Number) value; if (op1 instanceof BigDecimal bigDecimal) {
if (op1 instanceof BigDecimal) { newValue = new TypedValue(bigDecimal.add(BigDecimal.ONE), typedValue.getTypeDescriptor());
newValue = new TypedValue(((BigDecimal) op1).add(BigDecimal.ONE), typedValue.getTypeDescriptor());
} }
else if (op1 instanceof Double) { else if (op1 instanceof Double) {
newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor()); newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor());
@@ -69,8 +69,8 @@ public class OpInc extends Operator {
else if (op1 instanceof Float) { else if (op1 instanceof Float) {
newValue = new TypedValue(op1.floatValue() + 1.0f, typedValue.getTypeDescriptor()); newValue = new TypedValue(op1.floatValue() + 1.0f, typedValue.getTypeDescriptor());
} }
else if (op1 instanceof BigInteger) { else if (op1 instanceof BigInteger bigInteger) {
newValue = new TypedValue(((BigInteger) op1).add(BigInteger.ONE), typedValue.getTypeDescriptor()); newValue = new TypedValue(bigInteger.add(BigInteger.ONE), typedValue.getTypeDescriptor());
} }
else if (op1 instanceof Long) { else if (op1 instanceof Long) {
newValue = new TypedValue(op1.longValue() + 1L, typedValue.getTypeDescriptor()); newValue = new TypedValue(op1.longValue() + 1L, typedValue.getTypeDescriptor());

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -50,10 +50,7 @@ public class OpLE extends Operator {
this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left); this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right); this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
if (left instanceof Number && right instanceof Number) { if (left instanceof Number leftNumber && right instanceof Number rightNumber) {
Number leftNumber = (Number) left;
Number rightNumber = (Number) right;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -50,10 +50,7 @@ public class OpLT extends Operator {
this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left); this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right); this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
if (left instanceof Number && right instanceof Number) { if (left instanceof Number leftNumber && right instanceof Number rightNumber) {
Number leftNumber = (Number) left;
Number rightNumber = (Number) right;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@ import org.springframework.util.NumberUtils;
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso * @author Giovanni Dall'Oglio Risso
* @author Sam Brannen
* @since 3.0 * @since 3.0
*/ */
public class OpMinus extends Operator { public class OpMinus extends Operator {
@@ -58,38 +59,38 @@ public class OpMinus extends Operator {
if (this.children.length < 2) { // if only one operand, then this is unary minus if (this.children.length < 2) { // if only one operand, then this is unary minus
Object operand = leftOp.getValueInternal(state).getValue(); Object operand = leftOp.getValueInternal(state).getValue();
if (operand instanceof Number) { if (operand instanceof Number number) {
if (operand instanceof BigDecimal) { if (number instanceof BigDecimal bigDecimal) {
return new TypedValue(((BigDecimal) operand).negate()); return new TypedValue(bigDecimal.negate());
} }
else if (operand instanceof Double) { else if (number instanceof BigInteger bigInteger) {
return new TypedValue(bigInteger.negate());
}
else if (number instanceof Double) {
this.exitTypeDescriptor = "D"; this.exitTypeDescriptor = "D";
return new TypedValue(0 - ((Number) operand).doubleValue()); return new TypedValue(0 - number.doubleValue());
} }
else if (operand instanceof Float) { else if (number instanceof Float) {
this.exitTypeDescriptor = "F"; this.exitTypeDescriptor = "F";
return new TypedValue(0 - ((Number) operand).floatValue()); return new TypedValue(0 - number.floatValue());
} }
else if (operand instanceof BigInteger) { else if (number instanceof Long) {
return new TypedValue(((BigInteger) operand).negate());
}
else if (operand instanceof Long) {
this.exitTypeDescriptor = "J"; this.exitTypeDescriptor = "J";
return new TypedValue(0 - ((Number) operand).longValue()); return new TypedValue(0 - number.longValue());
} }
else if (operand instanceof Integer) { else if (number instanceof Integer) {
this.exitTypeDescriptor = "I"; this.exitTypeDescriptor = "I";
return new TypedValue(0 - ((Number) operand).intValue()); return new TypedValue(0 - number.intValue());
} }
else if (operand instanceof Short) { else if (number instanceof Short) {
return new TypedValue(0 - ((Number) operand).shortValue()); return new TypedValue(0 - number.shortValue());
} }
else if (operand instanceof Byte) { else if (number instanceof Byte) {
return new TypedValue(0 - ((Number) operand).byteValue()); return new TypedValue(0 - number.byteValue());
} }
else { else {
// Unknown Number subtypes -> best guess is double subtraction // Unknown Number subtype -> best guess is double subtraction
return new TypedValue(0 - ((Number) operand).doubleValue()); return new TypedValue(0 - number.doubleValue());
} }
} }
return state.operate(Operation.SUBTRACT, operand, null); return state.operate(Operation.SUBTRACT, operand, null);
@@ -98,10 +99,7 @@ public class OpMinus extends Operator {
Object left = leftOp.getValueInternal(state).getValue(); Object left = leftOp.getValueInternal(state).getValue();
Object right = getRightOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue();
if (left instanceof Number && right instanceof Number) { if (left instanceof Number leftNumber && right instanceof Number rightNumber) {
Number leftNumber = (Number) left;
Number rightNumber = (Number) right;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
@@ -134,9 +132,7 @@ public class OpMinus extends Operator {
} }
} }
if (left instanceof String && right instanceof Integer && ((String) left).length() == 1) { if (left instanceof String theString && right instanceof Integer theInteger && theString.length() == 1) {
String theString = (String) left;
Integer theInteger = (Integer) right;
// Implements character - int (ie. b - 1 = a) // Implements character - int (ie. b - 1 = a)
return new TypedValue(Character.toString((char) (theString.charAt(0) - theInteger))); return new TypedValue(Character.toString((char) (theString.charAt(0) - theInteger)));
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -48,10 +48,7 @@ public class OpModulus extends Operator {
Object leftOperand = getLeftOperand().getValueInternal(state).getValue(); Object leftOperand = getLeftOperand().getValueInternal(state).getValue();
Object rightOperand = getRightOperand().getValueInternal(state).getValue(); Object rightOperand = getRightOperand().getValueInternal(state).getValue();
if (leftOperand instanceof Number && rightOperand instanceof Number) { if (leftOperand instanceof Number leftNumber && rightOperand instanceof Number rightNumber) {
Number leftNumber = (Number) leftOperand;
Number rightNumber = (Number) rightOperand;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
@@ -79,7 +76,7 @@ public class OpModulus extends Operator {
return new TypedValue(leftNumber.intValue() % rightNumber.intValue()); return new TypedValue(leftNumber.intValue() % rightNumber.intValue());
} }
else { else {
// Unknown Number subtypes -> best guess is double division // Unknown Number subtype -> best guess is double division
return new TypedValue(leftNumber.doubleValue() % rightNumber.doubleValue()); return new TypedValue(leftNumber.doubleValue() % rightNumber.doubleValue());
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -72,10 +72,7 @@ public class OpMultiply extends Operator {
Object leftOperand = getLeftOperand().getValueInternal(state).getValue(); Object leftOperand = getLeftOperand().getValueInternal(state).getValue();
Object rightOperand = getRightOperand().getValueInternal(state).getValue(); Object rightOperand = getRightOperand().getValueInternal(state).getValue();
if (leftOperand instanceof Number && rightOperand instanceof Number) { if (leftOperand instanceof Number leftNumber && rightOperand instanceof Number rightNumber) {
Number leftNumber = (Number) leftOperand;
Number rightNumber = (Number) rightOperand;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
@@ -108,13 +105,8 @@ public class OpMultiply extends Operator {
} }
} }
if (leftOperand instanceof String && rightOperand instanceof Integer) { if (leftOperand instanceof String text && rightOperand instanceof Integer repeats) {
int repeats = (Integer) rightOperand; return new TypedValue(text.repeat(repeats));
StringBuilder result = new StringBuilder();
for (int i = 0; i < repeats; i++) {
result.append(leftOperand);
}
return new TypedValue(result.toString());
} }
return state.operate(Operation.MULTIPLY, leftOperand, rightOperand); return state.operate(Operation.MULTIPLY, leftOperand, rightOperand);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -85,10 +85,7 @@ public class OpPlus extends Operator {
TypedValue operandTwoValue = getRightOperand().getValueInternal(state); TypedValue operandTwoValue = getRightOperand().getValueInternal(state);
Object rightOperand = operandTwoValue.getValue(); Object rightOperand = operandTwoValue.getValue();
if (leftOperand instanceof Number && rightOperand instanceof Number) { if (leftOperand instanceof Number leftNumber && rightOperand instanceof Number rightNumber) {
Number leftNumber = (Number) leftOperand;
Number rightNumber = (Number) rightOperand;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
@@ -121,9 +118,9 @@ public class OpPlus extends Operator {
} }
} }
if (leftOperand instanceof String && rightOperand instanceof String) { if (leftOperand instanceof String leftString && rightOperand instanceof String rightString) {
this.exitTypeDescriptor = "Ljava/lang/String"; this.exitTypeDescriptor = "Ljava/lang/String";
return new TypedValue((String) leftOperand + rightOperand); return new TypedValue(leftString + rightString);
} }
if (leftOperand instanceof String) { if (leftOperand instanceof String) {
@@ -190,8 +187,7 @@ public class OpPlus extends Operator {
* them all to the same (on stack) StringBuilder. * them all to the same (on stack) StringBuilder.
*/ */
private void walk(MethodVisitor mv, CodeFlow cf, @Nullable SpelNodeImpl operand) { private void walk(MethodVisitor mv, CodeFlow cf, @Nullable SpelNodeImpl operand) {
if (operand instanceof OpPlus) { if (operand instanceof OpPlus plus) {
OpPlus plus = (OpPlus)operand;
walk(mv, cf, plus.getLeftOperand()); walk(mv, cf, plus.getLeftOperand());
walk(mv, cf, plus.getRightOperand()); walk(mv, cf, plus.getRightOperand());
} }

View File

@@ -36,6 +36,7 @@ import org.springframework.util.ObjectUtils;
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Giovanni Dall'Oglio Risso * @author Giovanni Dall'Oglio Risso
* @author Sam Brannen
* @since 3.0 * @since 3.0
*/ */
public abstract class Operator extends SpelNodeImpl { public abstract class Operator extends SpelNodeImpl {
@@ -261,10 +262,7 @@ public abstract class Operator extends SpelNodeImpl {
* @param right the right-hand operand value * @param right the right-hand operand value
*/ */
public static boolean equalityCheck(EvaluationContext context, @Nullable Object left, @Nullable Object right) { public static boolean equalityCheck(EvaluationContext context, @Nullable Object left, @Nullable Object right) {
if (left instanceof Number && right instanceof Number) { if (left instanceof Number leftNumber && right instanceof Number rightNumber) {
Number leftNumber = (Number) left;
Number rightNumber = (Number) right;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import org.springframework.expression.spel.support.BooleanTypedValue;
* *
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen
* @since 3.0 * @since 3.0
*/ */
public class OperatorMatches extends Operator { public class OperatorMatches extends Operator {
@@ -69,13 +70,12 @@ public class OperatorMatches extends Operator {
throw new SpelEvaluationException(leftOp.getStartPosition(), throw new SpelEvaluationException(leftOp.getStartPosition(),
SpelMessage.INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR, (Object) null); SpelMessage.INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR, (Object) null);
} }
if (!(right instanceof String)) { if (!(right instanceof String rightString)) {
throw new SpelEvaluationException(rightOp.getStartPosition(), throw new SpelEvaluationException(rightOp.getStartPosition(),
SpelMessage.INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR, right); SpelMessage.INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR, right);
} }
try { try {
String rightString = (String) right;
Pattern pattern = this.patternCache.get(rightString); Pattern pattern = this.patternCache.get(rightString);
if (pattern == null) { if (pattern == null) {
pattern = Pattern.compile(rightString); pattern = Pattern.compile(rightString);
@@ -111,7 +111,7 @@ public class OperatorMatches extends Operator {
private final CharSequence value; private final CharSequence value;
private AccessCount access; private final AccessCount access;
public MatcherInput(CharSequence value, AccessCount access) { public MatcherInput(CharSequence value, AccessCount access) {
this.value = value; this.value = value;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -47,10 +47,7 @@ public class OperatorPower extends Operator {
Object leftOperand = leftOp.getValueInternal(state).getValue(); Object leftOperand = leftOp.getValueInternal(state).getValue();
Object rightOperand = rightOp.getValueInternal(state).getValue(); Object rightOperand = rightOp.getValueInternal(state).getValue();
if (leftOperand instanceof Number && rightOperand instanceof Number) { if (leftOperand instanceof Number leftNumber && rightOperand instanceof Number rightNumber) {
Number leftNumber = (Number) leftOperand;
Number rightNumber = (Number) rightOperand;
if (leftNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
return new TypedValue(leftBigDecimal.pow(rightNumber.intValue())); return new TypedValue(leftBigDecimal.pow(rightNumber.intValue()));

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@ import org.springframework.util.ReflectionUtils;
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Clark Duplichien * @author Clark Duplichien
* @author Sam Brannen
* @since 3.0 * @since 3.0
*/ */
public class PropertyOrFieldReference extends SpelNodeImpl { public class PropertyOrFieldReference extends SpelNodeImpl {
@@ -91,8 +92,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
TypedValue tv = getValueInternal(state.getActiveContextObject(), state.getEvaluationContext(), TypedValue tv = getValueInternal(state.getActiveContextObject(), state.getEvaluationContext(),
state.getConfiguration().isAutoGrowNullReferences()); state.getConfiguration().isAutoGrowNullReferences());
PropertyAccessor accessorToUse = this.cachedReadAccessor; PropertyAccessor accessorToUse = this.cachedReadAccessor;
if (accessorToUse instanceof CompilablePropertyAccessor) { if (accessorToUse instanceof CompilablePropertyAccessor accessor) {
CompilablePropertyAccessor accessor = (CompilablePropertyAccessor) accessorToUse;
setExitTypeDescriptor(CodeFlow.toDescriptor(accessor.getPropertyType())); setExitTypeDescriptor(CodeFlow.toDescriptor(accessor.getPropertyType()));
} }
return tv; return tv;
@@ -196,8 +196,8 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
try { try {
for (PropertyAccessor accessor : accessorsToTry) { for (PropertyAccessor accessor : accessorsToTry) {
if (accessor.canRead(evalContext, contextObject.getValue(), name)) { if (accessor.canRead(evalContext, contextObject.getValue(), name)) {
if (accessor instanceof ReflectivePropertyAccessor) { if (accessor instanceof ReflectivePropertyAccessor reflectivePropertyAccessor) {
accessor = ((ReflectivePropertyAccessor) accessor).createOptimalAccessor( accessor = reflectivePropertyAccessor.createOptimalAccessor(
evalContext, contextObject.getValue(), name); evalContext, contextObject.getValue(), name);
} }
this.cachedReadAccessor = accessor; this.cachedReadAccessor = accessor;
@@ -330,9 +330,8 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
@Override @Override
public boolean isCompilable() { public boolean isCompilable() {
PropertyAccessor accessorToUse = this.cachedReadAccessor; return (this.cachedReadAccessor instanceof CompilablePropertyAccessor compilablePropertyAccessor &&
return (accessorToUse instanceof CompilablePropertyAccessor && compilablePropertyAccessor.isCompilable());
((CompilablePropertyAccessor) accessorToUse).isCompilable());
} }
@Override @Override
@@ -404,9 +403,8 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
public TypedValue getValue() { public TypedValue getValue() {
TypedValue value = TypedValue value =
this.ref.getValueInternal(this.contextObject, this.evalContext, this.autoGrowNullReferences); this.ref.getValueInternal(this.contextObject, this.evalContext, this.autoGrowNullReferences);
PropertyAccessor accessorToUse = this.ref.cachedReadAccessor; if (this.ref.cachedReadAccessor instanceof CompilablePropertyAccessor compilablePropertyAccessor) {
if (accessorToUse instanceof CompilablePropertyAccessor) { this.ref.setExitTypeDescriptor(CodeFlow.toDescriptor(compilablePropertyAccessor.getPropertyType()));
this.ref.setExitTypeDescriptor(CodeFlow.toDescriptor(((CompilablePropertyAccessor) accessorToUse).getPropertyType()));
} }
return value; return value;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -65,15 +65,15 @@ class Tokenizer {
} }
private String expressionString; private final String expressionString;
private char[] charsToProcess; private final char[] charsToProcess;
private int pos; private int pos;
private int max; private final int max;
private List<Token> tokens = new ArrayList<>(); private final List<Token> tokens = new ArrayList<>();
public Tokenizer(String inputData) { public Tokenizer(String inputData) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2020 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -123,7 +123,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return false; return false;
} }
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class<?> clazz ? clazz : target.getClass());
if (type.isArray() && name.equals("length")) { if (type.isArray() && name.equals("length")) {
return true; return true;
} }
@@ -160,7 +160,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
@Override @Override
public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException { public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException {
Assert.state(target != null, "Target must not be null"); Assert.state(target != null, "Target must not be null");
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class<?> clazz ? clazz : target.getClass());
if (type.isArray() && name.equals("length")) { if (type.isArray() && name.equals("length")) {
if (target instanceof Class) { if (target instanceof Class) {
@@ -231,7 +231,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return false; return false;
} }
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class<?> clazz ? clazz : target.getClass());
PropertyCacheKey cacheKey = new PropertyCacheKey(type, name, target instanceof Class); PropertyCacheKey cacheKey = new PropertyCacheKey(type, name, target instanceof Class);
if (this.writerCache.containsKey(cacheKey)) { if (this.writerCache.containsKey(cacheKey)) {
return true; return true;
@@ -269,7 +269,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
} }
Assert.state(target != null, "Target must not be null"); Assert.state(target != null, "Target must not be null");
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class<?> clazz ? clazz : target.getClass());
Object possiblyConvertedNewValue = newValue; Object possiblyConvertedNewValue = newValue;
TypeDescriptor typeDescriptor = getTypeDescriptor(context, target, name); TypeDescriptor typeDescriptor = getTypeDescriptor(context, target, name);
@@ -346,7 +346,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
@Nullable @Nullable
private TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) { private TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) {
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class<?> clazz ? clazz : target.getClass());
if (type.isArray() && name.equals("length")) { if (type.isArray() && name.equals("length")) {
return TypeDescriptor.valueOf(Integer.TYPE); return TypeDescriptor.valueOf(Integer.TYPE);
@@ -533,18 +533,18 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
if (target == null) { if (target == null) {
return this; return this;
} }
Class<?> clazz = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class<?> clazz ? clazz : target.getClass());
if (clazz.isArray()) { if (type.isArray()) {
return this; return this;
} }
PropertyCacheKey cacheKey = new PropertyCacheKey(clazz, name, target instanceof Class); PropertyCacheKey cacheKey = new PropertyCacheKey(type, name, target instanceof Class);
InvokerPair invocationTarget = this.readerCache.get(cacheKey); InvokerPair invocationTarget = this.readerCache.get(cacheKey);
if (invocationTarget == null || invocationTarget.member instanceof Method) { if (invocationTarget == null || invocationTarget.member instanceof Method) {
Method method = (Method) (invocationTarget != null ? invocationTarget.member : null); Method method = (Method) (invocationTarget != null ? invocationTarget.member : null);
if (method == null) { if (method == null) {
method = findGetterForProperty(name, clazz, target); method = findGetterForProperty(name, type, target);
if (method != null) { if (method != null) {
TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(method, -1)); TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(method, -1));
method = ClassUtils.getInterfaceMethodIfPossible(method); method = ClassUtils.getInterfaceMethodIfPossible(method);
@@ -561,7 +561,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
if (invocationTarget == null || invocationTarget.member instanceof Field) { if (invocationTarget == null || invocationTarget.member instanceof Field) {
Field field = (invocationTarget != null ? (Field) invocationTarget.member : null); Field field = (invocationTarget != null ? (Field) invocationTarget.member : null);
if (field == null) { if (field == null) {
field = findField(name, clazz, target instanceof Class); field = findField(name, type, target instanceof Class);
if (field != null) { if (field != null) {
invocationTarget = new InvokerPair(field, new TypeDescriptor(field)); invocationTarget = new InvokerPair(field, new TypeDescriptor(field));
ReflectionUtils.makeAccessible(field); ReflectionUtils.makeAccessible(field);
@@ -600,7 +600,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
private final String property; private final String property;
private boolean targetIsClass; private final boolean targetIsClass;
public PropertyCacheKey(Class<?> clazz, String name, boolean targetIsClass) { public PropertyCacheKey(Class<?> clazz, String name, boolean targetIsClass) {
this.clazz = clazz; this.clazz = clazz;
@@ -613,10 +613,9 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
if (this == other) { if (this == other) {
return true; return true;
} }
if (!(other instanceof PropertyCacheKey)) { if (!(other instanceof PropertyCacheKey otherKey)) {
return false; return false;
} }
PropertyCacheKey otherKey = (PropertyCacheKey) other;
return (this.clazz == otherKey.clazz && this.property.equals(otherKey.property) && return (this.clazz == otherKey.clazz && this.property.equals(otherKey.property) &&
this.targetIsClass == otherKey.targetIsClass); this.targetIsClass == otherKey.targetIsClass);
} }
@@ -676,13 +675,12 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
if (target == null) { if (target == null) {
return false; return false;
} }
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class<?> clazz ? clazz : target.getClass());
if (type.isArray()) { if (type.isArray()) {
return false; return false;
} }
if (this.member instanceof Method) { if (this.member instanceof Method method) {
Method method = (Method) this.member;
String getterName = "get" + StringUtils.capitalize(name); String getterName = "get" + StringUtils.capitalize(name);
if (getterName.equals(method.getName())) { if (getterName.equals(method.getName())) {
return true; return true;
@@ -697,8 +695,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
@Override @Override
public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException { public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException {
if (this.member instanceof Method) { if (this.member instanceof Method method) {
Method method = (Method) this.member;
try { try {
ReflectionUtils.makeAccessible(method); ReflectionUtils.makeAccessible(method);
Object value = method.invoke(target); Object value = method.invoke(target);
@@ -739,8 +736,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
@Override @Override
public Class<?> getPropertyType() { public Class<?> getPropertyType() {
if (this.member instanceof Method) { if (this.member instanceof Method method) {
return ((Method) this.member).getReturnType(); return method.getReturnType();
} }
else { else {
return ((Field) this.member).getType(); return ((Field) this.member).getType();
@@ -769,8 +766,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
} }
} }
if (this.member instanceof Method) { if (this.member instanceof Method method) {
Method method = (Method) this.member;
boolean isInterface = method.getDeclaringClass().isInterface(); boolean isInterface = method.getDeclaringClass().isInterface();
int opcode = (isStatic ? INVOKESTATIC : isInterface ? INVOKEINTERFACE : INVOKEVIRTUAL); int opcode = (isStatic ? INVOKESTATIC : isInterface ? INVOKEINTERFACE : INVOKEVIRTUAL);
mv.visitMethodInsn(opcode, classDesc, method.getName(), mv.visitMethodInsn(opcode, classDesc, method.getName(),

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -62,10 +62,7 @@ public class StandardTypeComparator implements TypeComparator {
} }
// Basic number comparisons // Basic number comparisons
if (left instanceof Number && right instanceof Number) { if (left instanceof Number leftNumber && right instanceof Number rightNumber) {
Number leftNumber = (Number) left;
Number rightNumber = (Number) right;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
@@ -95,7 +92,7 @@ public class StandardTypeComparator implements TypeComparator {
return Byte.compare(leftNumber.byteValue(), rightNumber.byteValue()); return Byte.compare(leftNumber.byteValue(), rightNumber.byteValue());
} }
else { else {
// Unknown Number subtypes -> best guess is double multiplication // Unknown Number subtype -> best guess is double multiplication
return Double.compare(leftNumber.doubleValue(), rightNumber.doubleValue()); return Double.compare(leftNumber.doubleValue(), rightNumber.doubleValue());
} }
} }