Apply 'instanceof pattern matching' in spring-expression

This commit is contained in:
Sam Brannen 2022-12-07 17:09:24 -05:00
parent 114d6a9256
commit f07a4587bb
10 changed files with 35 additions and 40 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 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.
@ -70,14 +70,14 @@ public class FunctionReference extends SpelNodeImpl {
if (value == TypedValue.NULL) { if (value == TypedValue.NULL) {
throw new SpelEvaluationException(getStartPosition(), SpelMessage.FUNCTION_NOT_DEFINED, this.name); throw new SpelEvaluationException(getStartPosition(), SpelMessage.FUNCTION_NOT_DEFINED, this.name);
} }
if (!(value.getValue() instanceof Method)) { if (!(value.getValue() instanceof Method function)) {
// Possibly a static Java method registered as a function // Possibly a static Java method registered as a function
throw new SpelEvaluationException( throw new SpelEvaluationException(
SpelMessage.FUNCTION_REFERENCE_CANNOT_BE_INVOKED, this.name, value.getClass()); SpelMessage.FUNCTION_REFERENCE_CANNOT_BE_INVOKED, this.name, value.getClass());
} }
try { try {
return executeFunctionJLRMethod(state, (Method) value.getValue()); return executeFunctionJLRMethod(state, function);
} }
catch (SpelEvaluationException ex) { catch (SpelEvaluationException ex) {
ex.setPosition(getStartPosition()); ex.setPosition(getStartPosition());

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 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.
@ -165,11 +165,11 @@ public class Indexer extends SpelNodeImpl {
this.indexedType = IndexedType.ARRAY; this.indexedType = IndexedType.ARRAY;
return new ArrayIndexingValueRef(state.getTypeConverter(), target, idx, targetDescriptor); return new ArrayIndexingValueRef(state.getTypeConverter(), target, idx, targetDescriptor);
} }
else if (target instanceof Collection) { else if (target instanceof Collection<?> collection) {
if (target instanceof List) { if (target instanceof List) {
this.indexedType = IndexedType.LIST; this.indexedType = IndexedType.LIST;
} }
return new CollectionIndexingValueRef((Collection<?>) target, idx, targetDescriptor, return new CollectionIndexingValueRef(collection, idx, targetDescriptor,
state.getTypeConverter(), state.getConfiguration().isAutoGrowCollections(), state.getTypeConverter(), state.getConfiguration().isAutoGrowCollections(),
state.getConfiguration().getMaximumAutoGrowSize()); state.getConfiguration().getMaximumAutoGrowSize());
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2020 the original author or authors. * Copyright 2002-2022 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.
@ -134,7 +134,7 @@ public class MethodReference extends SpelNodeImpl {
// either there was no accessor or it no longer existed // either there was no accessor or it no longer existed
executorToUse = findAccessorForMethod(argumentTypes, value, evaluationContext); executorToUse = findAccessorForMethod(argumentTypes, value, evaluationContext);
this.cachedExecutor = new CachedMethodExecutor( this.cachedExecutor = new CachedMethodExecutor(
executorToUse, (value instanceof Class ? (Class<?>) value : null), targetType, argumentTypes); executorToUse, (value instanceof Class<?> clazz ? clazz : null), targetType, argumentTypes);
try { try {
return executorToUse.execute(evaluationContext, value, arguments); return executorToUse.execute(evaluationContext, value, arguments);
} }
@ -216,7 +216,7 @@ public class MethodReference extends SpelNodeImpl {
String method = FormatHelper.formatMethodForMessage(this.name, argumentTypes); String method = FormatHelper.formatMethodForMessage(this.name, argumentTypes);
String className = FormatHelper.formatClassNameForMessage( String className = FormatHelper.formatClassNameForMessage(
targetObject instanceof Class ? ((Class<?>) targetObject) : targetObject.getClass()); targetObject instanceof Class<?> clazz ? clazz : targetObject.getClass());
if (accessException != null) { if (accessException != null) {
throw new SpelEvaluationException( throw new SpelEvaluationException(
getStartPosition(), accessException, SpelMessage.PROBLEM_LOCATING_METHOD, method, className); getStartPosition(), accessException, SpelMessage.PROBLEM_LOCATING_METHOD, method, className);
@ -233,8 +233,8 @@ public class MethodReference extends SpelNodeImpl {
private void throwSimpleExceptionIfPossible(Object value, AccessException ex) { private void throwSimpleExceptionIfPossible(Object value, AccessException ex) {
if (ex.getCause() instanceof InvocationTargetException) { if (ex.getCause() instanceof InvocationTargetException) {
Throwable rootCause = ex.getCause().getCause(); Throwable rootCause = ex.getCause().getCause();
if (rootCause instanceof RuntimeException) { if (rootCause instanceof RuntimeException runtimeException) {
throw (RuntimeException) rootCause; throw runtimeException;
} }
throw new ExpressionInvocationTargetException(getStartPosition(), throw new ExpressionInvocationTargetException(getStartPosition(),
"A problem occurred when trying to execute method '" + this.name + "A problem occurred when trying to execute method '" + this.name +
@ -244,8 +244,8 @@ public class MethodReference extends SpelNodeImpl {
private void updateExitTypeDescriptor() { private void updateExitTypeDescriptor() {
CachedMethodExecutor executorToCheck = this.cachedExecutor; CachedMethodExecutor executorToCheck = this.cachedExecutor;
if (executorToCheck != null && executorToCheck.get() instanceof ReflectiveMethodExecutor) { if (executorToCheck != null && executorToCheck.get() instanceof ReflectiveMethodExecutor reflectiveMethodExecutor) {
Method method = ((ReflectiveMethodExecutor) executorToCheck.get()).getMethod(); Method method = reflectiveMethodExecutor.getMethod();
String descriptor = CodeFlow.toDescriptor(method.getReturnType()); String descriptor = CodeFlow.toDescriptor(method.getReturnType());
if (this.nullSafe && CodeFlow.isPrimitive(descriptor)) { if (this.nullSafe && CodeFlow.isPrimitive(descriptor)) {
this.originalPrimitiveExitTypeDescriptor = descriptor; this.originalPrimitiveExitTypeDescriptor = descriptor;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 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.
@ -53,12 +53,11 @@ public class OperatorBetween extends Operator {
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException { public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Object left = getLeftOperand().getValueInternal(state).getValue(); Object left = getLeftOperand().getValueInternal(state).getValue();
Object right = getRightOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue();
if (!(right instanceof List) || ((List<?>) right).size() != 2) { if (!(right instanceof List<?> list) || list.size() != 2) {
throw new SpelEvaluationException(getRightOperand().getStartPosition(), throw new SpelEvaluationException(getRightOperand().getStartPosition(),
SpelMessage.BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST); SpelMessage.BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST);
} }
List<?> list = (List<?>) right;
Object low = list.get(0); Object low = list.get(0);
Object high = list.get(1); Object high = list.get(1);
TypeComparator comp = state.getTypeComparator(); TypeComparator comp = state.getTypeComparator();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 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,12 +62,11 @@ public class OperatorInstanceof extends Operator {
Object leftValue = left.getValue(); Object leftValue = left.getValue();
Object rightValue = right.getValue(); Object rightValue = right.getValue();
BooleanTypedValue result; BooleanTypedValue result;
if (!(rightValue instanceof Class)) { if (!(rightValue instanceof Class<?> rightClass)) {
throw new SpelEvaluationException(getRightOperand().getStartPosition(), throw new SpelEvaluationException(getRightOperand().getStartPosition(),
SpelMessage.INSTANCEOF_OPERATOR_NEEDS_CLASS_OPERAND, SpelMessage.INSTANCEOF_OPERATOR_NEEDS_CLASS_OPERAND,
(rightValue == null ? "null" : rightValue.getClass().getName())); (rightValue == null ? "null" : rightValue.getClass().getName()));
} }
Class<?> rightClass = (Class<?>) rightValue;
if (leftValue == null) { if (leftValue == null) {
result = BooleanTypedValue.FALSE; // null is not an instanceof anything result = BooleanTypedValue.FALSE; // null is not an instanceof anything
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 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.
@ -70,8 +70,7 @@ public class Projection extends SpelNodeImpl {
// has two fields 'key' and 'value' that refer to the map entries key // has two fields 'key' and 'value' that refer to the map entries key
// and value, and they can be referenced in the operation // and value, and they can be referenced in the operation
// eg. {'a':'y','b':'n'}.![value=='y'?key:null]" == ['a', null] // eg. {'a':'y','b':'n'}.![value=='y'?key:null]" == ['a', null]
if (operand instanceof Map) { if (operand instanceof Map<?, ?> mapData) {
Map<?, ?> mapData = (Map<?, ?>) operand;
List<Object> result = new ArrayList<>(); List<Object> result = new ArrayList<>();
for (Map.Entry<?, ?> entry : mapData.entrySet()) { for (Map.Entry<?, ?> entry : mapData.entrySet()) {
try { try {
@ -88,8 +87,8 @@ public class Projection extends SpelNodeImpl {
} }
if (operand instanceof Iterable || operandIsArray) { if (operand instanceof Iterable || operandIsArray) {
Iterable<?> data = (operand instanceof Iterable ? Iterable<?> data = (operand instanceof Iterable<?> iterable ?
(Iterable<?>) operand : Arrays.asList(ObjectUtils.toObjectArray(operand))); iterable : Arrays.asList(ObjectUtils.toObjectArray(operand)));
List<Object> result = new ArrayList<>(); List<Object> result = new ArrayList<>();
Class<?> arrayElementType = null; Class<?> arrayElementType = null;

View File

@ -87,8 +87,7 @@ public class Selection extends SpelNodeImpl {
Object operand = op.getValue(); Object operand = op.getValue();
SpelNodeImpl selectionCriteria = this.children[0]; SpelNodeImpl selectionCriteria = this.children[0];
if (operand instanceof Map) { if (operand instanceof Map<?, ?> mapdata) {
Map<?, ?> mapdata = (Map<?, ?>) operand;
// TODO don't lose generic info for the new map // TODO don't lose generic info for the new map
Map<Object, Object> result = new HashMap<>(); Map<Object, Object> result = new HashMap<>();
Object lastKey = null; Object lastKey = null;
@ -99,8 +98,8 @@ public class Selection extends SpelNodeImpl {
state.pushActiveContextObject(kvPair); state.pushActiveContextObject(kvPair);
state.enterScope(); state.enterScope();
Object val = selectionCriteria.getValueInternal(state).getValue(); Object val = selectionCriteria.getValueInternal(state).getValue();
if (val instanceof Boolean) { if (val instanceof Boolean b) {
if ((Boolean) val) { if (b) {
if (this.variant == FIRST) { if (this.variant == FIRST) {
result.put(entry.getKey(), entry.getValue()); result.put(entry.getKey(), entry.getValue());
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this); return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this);
@ -135,8 +134,8 @@ public class Selection extends SpelNodeImpl {
} }
if (operand instanceof Iterable || ObjectUtils.isArray(operand)) { if (operand instanceof Iterable || ObjectUtils.isArray(operand)) {
Iterable<?> data = (operand instanceof Iterable ? Iterable<?> data = (operand instanceof Iterable<?> iterable ?
(Iterable<?>) operand : Arrays.asList(ObjectUtils.toObjectArray(operand))); iterable : Arrays.asList(ObjectUtils.toObjectArray(operand)));
List<Object> result = new ArrayList<>(); List<Object> result = new ArrayList<>();
int index = 0; int index = 0;
@ -145,8 +144,8 @@ public class Selection extends SpelNodeImpl {
state.pushActiveContextObject(new TypedValue(element)); state.pushActiveContextObject(new TypedValue(element));
state.enterScope("index", index); state.enterScope("index", index);
Object val = selectionCriteria.getValueInternal(state).getValue(); Object val = selectionCriteria.getValueInternal(state).getValue();
if (val instanceof Boolean) { if (val instanceof Boolean b) {
if ((Boolean) val) { if (b) {
if (this.variant == FIRST) { if (this.variant == FIRST) {
return new ValueRef.TypedValueHolderValueRef(new TypedValue(element), this); return new ValueRef.TypedValueHolderValueRef(new TypedValue(element), this);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2022 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.
@ -144,7 +144,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
if (obj == null) { if (obj == null) {
return null; return null;
} }
return (obj instanceof Class ? ((Class<?>) obj) : obj.getClass()); return (obj instanceof Class<?> clazz ? clazz : obj.getClass());
} }
@Override @Override
@ -207,8 +207,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
protected static void generateCodeForArguments(MethodVisitor mv, CodeFlow cf, Member member, SpelNodeImpl[] arguments) { protected static void generateCodeForArguments(MethodVisitor mv, CodeFlow cf, Member member, SpelNodeImpl[] arguments) {
String[] paramDescriptors = null; String[] paramDescriptors = null;
boolean isVarargs = false; boolean isVarargs = false;
if (member instanceof Constructor) { if (member instanceof Constructor<?> ctor) {
Constructor<?> ctor = (Constructor<?>) member;
paramDescriptors = CodeFlow.toDescriptors(ctor.getParameterTypes()); paramDescriptors = CodeFlow.toDescriptors(ctor.getParameterTypes());
isVarargs = ctor.isVarArgs(); isVarargs = ctor.isVarArgs();
} }

View File

@ -252,7 +252,7 @@ public final class SpelCompiler implements Opcodes {
* {@code false} otherwise * {@code false} otherwise
*/ */
public static boolean compile(Expression expression) { public static boolean compile(Expression expression) {
return (expression instanceof SpelExpression && ((SpelExpression) expression).compileExpression()); return (expression instanceof SpelExpression spelExpression && spelExpression.compileExpression());
} }
/** /**
@ -261,8 +261,8 @@ public final class SpelCompiler implements Opcodes {
* @param expression the expression * @param expression the expression
*/ */
public static void revertToInterpreted(Expression expression) { public static void revertToInterpreted(Expression expression) {
if (expression instanceof SpelExpression) { if (expression instanceof SpelExpression spelExpression) {
((SpelExpression) expression).revertToInterpreted(); spelExpression.revertToInterpreted();
} }
} }

View File

@ -114,7 +114,7 @@ public class ReflectiveMethodResolver implements MethodResolver {
try { try {
TypeConverter typeConverter = context.getTypeConverter(); TypeConverter typeConverter = context.getTypeConverter();
Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass()); Class<?> type = (targetObject instanceof Class<?> clazz ? clazz : targetObject.getClass());
ArrayList<Method> methods = new ArrayList<>(getMethods(type, targetObject)); ArrayList<Method> methods = new ArrayList<>(getMethods(type, targetObject));
// If a filter is registered for this type, call it // If a filter is registered for this type, call it