From 5fd9fab0ce07ef7596b3e7c5ba2f6f12adcf8a71 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 7 Feb 2024 23:40:11 +0100 Subject: [PATCH] Polishing (backported from main) --- .../language-ref/collection-projection.adoc | 12 ++++++---- .../language-ref/collection-selection.adoc | 23 ++++++++++--------- .../server-setup-options.adoc | 2 +- .../expression/TypedValue.java | 5 ++-- .../expression/spel/ast/Selection.java | 21 +++++++++-------- .../servlet/function/RequestPredicates.java | 12 ++++++++-- 6 files changed, 44 insertions(+), 31 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/core/expressions/language-ref/collection-projection.adoc b/framework-docs/modules/ROOT/pages/core/expressions/language-ref/collection-projection.adoc index 83f492766dd..efc43fe8c1c 100644 --- a/framework-docs/modules/ROOT/pages/core/expressions/language-ref/collection-projection.adoc +++ b/framework-docs/modules/ROOT/pages/core/expressions/language-ref/collection-projection.adoc @@ -4,7 +4,7 @@ Projection lets a collection drive the evaluation of a sub-expression, and the result is a new collection. The syntax for projection is `.![projectionExpression]`. For example, suppose we have a list of inventors but want the list of cities where they were born. -Effectively, we want to evaluate 'placeOfBirth.city' for every entry in the inventor +Effectively, we want to evaluate `placeOfBirth.city` for every entry in the inventor list. The following example uses projection to do so: [tabs] @@ -13,16 +13,18 @@ Java:: + [source,java,indent=0,subs="verbatim,quotes",role="primary"] ---- - // returns ['Smiljan', 'Idvor' ] - List placesOfBirth = (List)parser.parseExpression("members.![placeOfBirth.city]"); + // evaluates to ["SmilJan", "Idvor"] + List placesOfBirth = parser.parseExpression("members.![placeOfBirth.city]") + .getValue(societyContext, List.class); ---- Kotlin:: + [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] ---- - // returns ['Smiljan', 'Idvor' ] - val placesOfBirth = parser.parseExpression("members.![placeOfBirth.city]") as List<*> + // evaluates to ["SmilJan", "Idvor"] + val placesOfBirth = parser.parseExpression("members.![placeOfBirth.city]") + .getValue(societyContext) as List<*> ---- ====== diff --git a/framework-docs/modules/ROOT/pages/core/expressions/language-ref/collection-selection.adoc b/framework-docs/modules/ROOT/pages/core/expressions/language-ref/collection-selection.adoc index 3f87541a81c..f0f70ffad9a 100644 --- a/framework-docs/modules/ROOT/pages/core/expressions/language-ref/collection-selection.adoc +++ b/framework-docs/modules/ROOT/pages/core/expressions/language-ref/collection-selection.adoc @@ -28,13 +28,14 @@ Kotlin:: ====== Selection is supported for arrays and anything that implements `java.lang.Iterable` or -`java.util.Map`. For a list or array, the selection criteria is evaluated against each -individual element. Against a map, the selection criteria is evaluated against each map -entry (objects of the Java type `Map.Entry`). Each map entry has its `key` and `value` -accessible as properties for use in the selection. +`java.util.Map`. For an array or `Iterable`, the selection expression is evaluated +against each individual element. Against a map, the selection expression is evaluated +against each map entry (objects of the Java type `Map.Entry`). Each map entry has its +`key` and `value` accessible as properties for use in the selection. -The following expression returns a new map that consists of those elements of the -original map where the entry's value is less than 27: +Given a `Map` stored in a variable named `#map`, the following expression returns a new +map that consists of those elements of the original map where the entry's value is less +than 27: [tabs] ====== @@ -42,21 +43,21 @@ Java:: + [source,java,indent=0,subs="verbatim,quotes",role="primary"] ---- - Map newMap = parser.parseExpression("map.?[value<27]").getValue(); + Map newMap = parser.parseExpression("#map.?[value < 27]").getValue(Map.class); ---- Kotlin:: + [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] ---- - val newMap = parser.parseExpression("map.?[value<27]").getValue() + val newMap = parser.parseExpression("#map.?[value < 27]").getValue() as Map ---- ====== In addition to returning all the selected elements, you can retrieve only the first or -the last element. To obtain the first element matching the selection, the syntax is -`.^[selectionExpression]`. To obtain the last matching selection, the syntax is -`.$[selectionExpression]`. +the last element. To obtain the first element matching the selection expression, the +syntax is `.^[selectionExpression]`. To obtain the last element matching the selection +expression, the syntax is `.$[selectionExpression]`. diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc b/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc index b38d69ed683..9dd0498d4e9 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc +++ b/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc @@ -152,7 +152,7 @@ Kotlin:: @Autowired lateinit var accountService: AccountService - lateinit mockMvc: MockMvc + lateinit var mockMvc: MockMvc @BeforeEach fun setup(wac: WebApplicationContext) { diff --git a/spring-expression/src/main/java/org/springframework/expression/TypedValue.java b/spring-expression/src/main/java/org/springframework/expression/TypedValue.java index ccd8b572352..b97020a259e 100644 --- a/spring-expression/src/main/java/org/springframework/expression/TypedValue.java +++ b/spring-expression/src/main/java/org/springframework/expression/TypedValue.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,8 @@ import org.springframework.util.ObjectUtils; /** * Encapsulates an object and a {@link TypeDescriptor} that describes it. - * The type descriptor can contain generic declarations that would not + * + *

The type descriptor can contain generic declarations that would not * be accessible through a simple {@code getClass()} call on the object. * * @author Andy Clement diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java index 72f9aa6f0e8..374a9da4d93 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 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. @@ -36,7 +36,9 @@ import org.springframework.util.ObjectUtils; /** * Represents selection over a map or collection. - * For example: {1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this) == 'y'} returns [2, 4, 6, 8, 10] + * + *

For example, {1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this)} evaluates + * to {@code [2, 4, 6, 8, 10]}. * *

Basically a subset of the input data is returned based on the * evaluation of the expression supplied as selection criteria. @@ -100,11 +102,10 @@ public class Selection extends SpelNodeImpl { Object val = selectionCriteria.getValueInternal(state).getValue(); if (val instanceof Boolean b) { if (b) { + result.put(entry.getKey(), entry.getValue()); if (this.variant == FIRST) { - result.put(entry.getKey(), entry.getValue()); return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this); } - result.put(entry.getKey(), entry.getValue()); lastKey = entry.getKey(); } } @@ -120,22 +121,22 @@ public class Selection extends SpelNodeImpl { } if ((this.variant == FIRST || this.variant == LAST) && result.isEmpty()) { - return new ValueRef.TypedValueHolderValueRef(new TypedValue(null), this); + return new ValueRef.TypedValueHolderValueRef(TypedValue.NULL, this); } if (this.variant == LAST) { Map resultMap = new HashMap<>(); Object lastValue = result.get(lastKey); - resultMap.put(lastKey,lastValue); - return new ValueRef.TypedValueHolderValueRef(new TypedValue(resultMap),this); + resultMap.put(lastKey, lastValue); + return new ValueRef.TypedValueHolderValueRef(new TypedValue(resultMap), this); } - return new ValueRef.TypedValueHolderValueRef(new TypedValue(result),this); + return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this); } if (operand instanceof Iterable || ObjectUtils.isArray(operand)) { - Iterable data = (operand instanceof Iterable iterable ? - iterable : Arrays.asList(ObjectUtils.toObjectArray(operand))); + Iterable data = (operand instanceof Iterable iterable ? iterable : + Arrays.asList(ObjectUtils.toObjectArray(operand))); List result = new ArrayList<>(); int index = 0; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RequestPredicates.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RequestPredicates.java index b71277ed16d..9923bfd7cfb 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RequestPredicates.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RequestPredicates.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. @@ -106,6 +106,7 @@ public abstract class RequestPredicates { * against the given path pattern. * @param pattern the pattern to match to * @return a predicate that tests against the given path pattern + * @see org.springframework.web.util.pattern.PathPattern */ public static RequestPredicate path(String pattern) { Assert.notNull(pattern, "'pattern' must not be null"); @@ -168,6 +169,7 @@ public abstract class RequestPredicates { * @param pattern the path pattern to match against * @return a predicate that matches if the request method is GET and if the given pattern * matches against the request path + * @see org.springframework.web.util.pattern.PathPattern */ public static RequestPredicate GET(String pattern) { return method(HttpMethod.GET).and(path(pattern)); @@ -179,6 +181,7 @@ public abstract class RequestPredicates { * @param pattern the path pattern to match against * @return a predicate that matches if the request method is HEAD and if the given pattern * matches against the request path + * @see org.springframework.web.util.pattern.PathPattern */ public static RequestPredicate HEAD(String pattern) { return method(HttpMethod.HEAD).and(path(pattern)); @@ -190,6 +193,7 @@ public abstract class RequestPredicates { * @param pattern the path pattern to match against * @return a predicate that matches if the request method is POST and if the given pattern * matches against the request path + * @see org.springframework.web.util.pattern.PathPattern */ public static RequestPredicate POST(String pattern) { return method(HttpMethod.POST).and(path(pattern)); @@ -201,6 +205,7 @@ public abstract class RequestPredicates { * @param pattern the path pattern to match against * @return a predicate that matches if the request method is PUT and if the given pattern * matches against the request path + * @see org.springframework.web.util.pattern.PathPattern */ public static RequestPredicate PUT(String pattern) { return method(HttpMethod.PUT).and(path(pattern)); @@ -212,6 +217,7 @@ public abstract class RequestPredicates { * @param pattern the path pattern to match against * @return a predicate that matches if the request method is PATCH and if the given pattern * matches against the request path + * @see org.springframework.web.util.pattern.PathPattern */ public static RequestPredicate PATCH(String pattern) { return method(HttpMethod.PATCH).and(path(pattern)); @@ -223,6 +229,7 @@ public abstract class RequestPredicates { * @param pattern the path pattern to match against * @return a predicate that matches if the request method is DELETE and if the given pattern * matches against the request path + * @see org.springframework.web.util.pattern.PathPattern */ public static RequestPredicate DELETE(String pattern) { return method(HttpMethod.DELETE).and(path(pattern)); @@ -234,6 +241,7 @@ public abstract class RequestPredicates { * @param pattern the path pattern to match against * @return a predicate that matches if the request method is OPTIONS and if the given pattern * matches against the request path + * @see org.springframework.web.util.pattern.PathPattern */ public static RequestPredicate OPTIONS(String pattern) { return method(HttpMethod.OPTIONS).and(path(pattern)); @@ -317,7 +325,6 @@ public abstract class RequestPredicates { else { return newPattern; } - } @@ -337,6 +344,7 @@ public abstract class RequestPredicates { * Receive notification of a path predicate. * @param pattern the path pattern that makes up the predicate * @see RequestPredicates#path(String) + * @see org.springframework.web.util.pattern.PathPattern */ void path(String pattern);