diff --git a/spring-expression/src/main/java/org/springframework/expression/OperatorOverloader.java b/spring-expression/src/main/java/org/springframework/expression/OperatorOverloader.java index 2e6d431ed85..8bece1f0fef 100644 --- a/spring-expression/src/main/java/org/springframework/expression/OperatorOverloader.java +++ b/spring-expression/src/main/java/org/springframework/expression/OperatorOverloader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +19,9 @@ package org.springframework.expression; import org.springframework.lang.Nullable; /** - * By default the mathematical operators {@link Operation} support simple types - * like numbers. By providing an implementation of OperatorOverloader, a user - * of the expression language can support these operations on other types. + * By default, the mathematical operators defined in {@link Operation} support simple + * types like numbers. By providing an implementation of {@code OperatorOverloader}, + * a user of the expression language can support these operations on other types. * * @author Andy Clement * @since 3.0 @@ -29,21 +29,21 @@ import org.springframework.lang.Nullable; public interface OperatorOverloader { /** - * Return true if the operator overloader supports the specified operation - * between the two operands and so should be invoked to handle it. + * Return {@code true} if this operator overloader supports the specified + * operation on the two operands and should be invoked to handle it. * @param operation the operation to be performed * @param leftOperand the left operand * @param rightOperand the right operand - * @return true if the OperatorOverloader supports the specified operation - * between the two operands + * @return true if this {@code OperatorOverloader} supports the specified + * operation between the two operands * @throws EvaluationException if there is a problem performing the operation */ boolean overridesOperation(Operation operation, @Nullable Object leftOperand, @Nullable Object rightOperand) throws EvaluationException; /** - * Execute the specified operation on two operands, returning a result. - * See {@link Operation} for supported operations. + * Perform the specified operation on the two operands, returning a result. + *
See {@link Operation} for supported operations. * @param operation the operation to be performed * @param leftOperand the left operand * @param rightOperand the right operand diff --git a/spring-expression/src/main/java/org/springframework/expression/common/CompositeStringExpression.java b/spring-expression/src/main/java/org/springframework/expression/common/CompositeStringExpression.java index a37cb2162eb..c98a5434015 100644 --- a/spring-expression/src/main/java/org/springframework/expression/common/CompositeStringExpression.java +++ b/spring-expression/src/main/java/org/springframework/expression/common/CompositeStringExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,17 +24,19 @@ import org.springframework.expression.TypedValue; import org.springframework.lang.Nullable; /** - * Represents a template expression broken into pieces. Each piece will be an Expression - * but pure text parts to the template will be represented as LiteralExpression objects. - * An example of a template expression might be: + * Represents a template expression broken into pieces. + * + *
Each piece will be an {@link Expression}, but pure text parts of the + * template will be represented as {@link LiteralExpression} objects. An example + * of a template expression might be: * *
* "Hello ${getName()}"
*
*
- * which will be represented as a CompositeStringExpression of two parts. The first part
- * being a LiteralExpression representing 'Hello ' and the second part being a real
- * expression that will call {@code getName()} when invoked.
+ * which will be represented as a {@code CompositeStringExpression} of two parts:
+ * the first part being a {@link LiteralExpression} representing 'Hello ' and the
+ * second part being a real expression that will call {@code getName()} when invoked.
*
* @author Andy Clement
* @author Juergen Hoeller
diff --git a/spring-expression/src/main/java/org/springframework/expression/common/LiteralExpression.java b/spring-expression/src/main/java/org/springframework/expression/common/LiteralExpression.java
index 07c64bd9f61..dbe37534215 100644
--- a/spring-expression/src/main/java/org/springframework/expression/common/LiteralExpression.java
+++ b/spring-expression/src/main/java/org/springframework/expression/common/LiteralExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,9 +24,11 @@ import org.springframework.expression.TypedValue;
import org.springframework.lang.Nullable;
/**
- * A very simple hardcoded implementation of the Expression interface that represents a
- * string literal. It is used with CompositeStringExpression when representing a template
- * expression which is made up of pieces - some being real expressions to be handled by
+ * A very simple, hard-coded implementation of the {@link Expression} interface
+ * that represents a string literal.
+ *
+ * It is used with {@link CompositeStringExpression} when representing a template
+ * expression which is made up of pieces, some being real expressions to be handled by
* an EL implementation like SpEL, and some being just textual elements.
*
* @author Andy Clement
diff --git a/spring-expression/src/main/java/org/springframework/expression/common/TemplateAwareExpressionParser.java b/spring-expression/src/main/java/org/springframework/expression/common/TemplateAwareExpressionParser.java
index e0fb6bc0b41..f979a258fb4 100644
--- a/spring-expression/src/main/java/org/springframework/expression/common/TemplateAwareExpressionParser.java
+++ b/spring-expression/src/main/java/org/springframework/expression/common/TemplateAwareExpressionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -80,11 +80,11 @@ public abstract class TemplateAwareExpressionParser implements ExpressionParser
* result, evaluating all returned expressions and concatenating the results produces
* the complete evaluated string. Unwrapping is only done of the outermost delimiters
* found, so the string 'hello ${foo${abc}}' would break into the pieces 'hello ' and
- * 'foo${abc}'. This means that expression languages that used ${..} as part of their
+ * 'foo${abc}'. This means that expression languages that use ${..} as part of their
* functionality are supported without any problem. The parsing is aware of the
* structure of an embedded expression. It assumes that parentheses '(', square
- * brackets '[' and curly brackets '}' must be in pairs within the expression unless
- * they are within a string literal and a string literal starts and terminates with a
+ * brackets '[', and curly brackets '}' must be in pairs within the expression unless
+ * they are within a string literal and the string literal starts and terminates with a
* single quote '.
* @param expressionString the expression string
* @return the parsed expressions
@@ -238,48 +238,33 @@ public abstract class TemplateAwareExpressionParser implements ExpressionParser
/**
* This captures a type of bracket and the position in which it occurs in the
* expression. The positional information is used if an error has to be reported
- * because the related end bracket cannot be found. Bracket is used to describe:
- * square brackets [] round brackets () and curly brackets {}
+ * because the related end bracket cannot be found. Bracket is used to describe
+ * square brackets [], round brackets (), and curly brackets {}.
*/
- private static class Bracket {
-
- char bracket;
-
- int pos;
-
- Bracket(char bracket, int pos) {
- this.bracket = bracket;
- this.pos = pos;
- }
+ private record Bracket(char bracket, int pos) {
boolean compatibleWithCloseBracket(char closeBracket) {
- if (this.bracket == '{') {
- return closeBracket == '}';
- }
- else if (this.bracket == '[') {
- return closeBracket == ']';
- }
- return closeBracket == ')';
+ return switch (this.bracket) {
+ case '{' -> closeBracket == '}';
+ case '[' -> closeBracket == ']';
+ default -> closeBracket == ')';
+ };
}
static char theOpenBracketFor(char closeBracket) {
- if (closeBracket == '}') {
- return '{';
- }
- else if (closeBracket == ']') {
- return '[';
- }
- return '(';
+ return switch (closeBracket) {
+ case '}' -> '{';
+ case ']' -> '[';
+ default -> '(';
+ };
}
static char theCloseBracketFor(char openBracket) {
- if (openBracket == '{') {
- return '}';
- }
- else if (openBracket == '[') {
- return ']';
- }
- return ')';
+ return switch (openBracket) {
+ case '{' -> '}';
+ case '[' -> ']';
+ default -> ')';
+ };
}
}
diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java
index 999c1c537ad..c81ca08446d 100644
--- a/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java
+++ b/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.EvaluationException;
import org.springframework.expression.Operation;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -223,7 +222,7 @@ class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
- void typeLocator() throws EvaluationException {
+ void typeLocator() {
assertThat(state.getEvaluationContext().getTypeLocator()).isNotNull();
assertThat(state.findType("java.lang.Integer")).isEqualTo(Integer.class);
assertThatExceptionOfType(SpelEvaluationException.class)
@@ -232,7 +231,7 @@ class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
- void typeConversion() throws EvaluationException {
+ void typeConversion() {
String s = (String) state.convertValue(34, TypeDescriptor.valueOf(String.class));
assertThat(s).isEqualTo("34");
diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/OperatorOverloaderTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/OperatorOverloaderTests.java
index 0dee9d5d8a3..bfac9bb1a3f 100644
--- a/spring-expression/src/test/java/org/springframework/expression/spel/OperatorOverloaderTests.java
+++ b/spring-expression/src/test/java/org/springframework/expression/spel/OperatorOverloaderTests.java
@@ -18,56 +18,50 @@ package org.springframework.expression.spel;
import org.junit.jupiter.api.Test;
-import org.springframework.expression.EvaluationException;
import org.springframework.expression.Operation;
import org.springframework.expression.OperatorOverloader;
-import org.springframework.expression.spel.standard.SpelExpression;
-import org.springframework.expression.spel.support.StandardEvaluationContext;
-
-import static org.assertj.core.api.Assertions.assertThat;
/**
- * Test providing operator support
+ * Tests for custom {@link OperatorOverloader} support.
*
* @author Andy Clement
+ * @author Sam Brannen
*/
class OperatorOverloaderTests extends AbstractExpressionTests {
@Test
- void testSimpleOperations() {
- // no built-in support for this:
- evaluateAndCheckError("'abc'-true",SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES);
+ void simpleOperations() {
+ // default behavior
+ evaluate("'abc' + true", "abctrue", String.class);
+ evaluate("'abc' + null", "abcnull", String.class);
- StandardEvaluationContext eContext = TestScenarioCreator.getTestEvaluationContext();
- eContext.setOperatorOverloader(new StringAndBooleanAddition());
+ // no built-in support for