Apply 'instanceof pattern matching' in spring-expression
This commit is contained in:
parent
114d6a9256
commit
f07a4587bb
|
@ -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());
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue