Skip to content

Commit 80b8e12

Browse files
committed
Polishing.
Allow nullable OffsetScrollPosition and add support for values wrapped within Optional. Update tests. Reformat code. Add issue tags to tests. See #2856 Original pull request: #2861
1 parent 391607b commit 80b8e12

6 files changed

+220
-147
lines changed

src/main/java/org/springframework/data/web/OffsetScrollPositionArgumentResolver.java

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2023 the original author or authors.
2+
* Copyright 2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
1717

1818
import org.springframework.core.MethodParameter;
1919
import org.springframework.data.domain.OffsetScrollPosition;
20-
import org.springframework.lang.NonNull;
2120
import org.springframework.lang.Nullable;
2221
import org.springframework.web.bind.WebDataBinder;
2322
import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -27,27 +26,31 @@
2726

2827
/**
2928
* Argument resolver to extract a {@link OffsetScrollPosition} object from a {@link NativeWebRequest} for a particular
30-
* {@link MethodParameter}. A {@link OffsetScrollPositionArgumentResolver} can either resolve {@link OffsetScrollPosition} itself or wrap another
31-
* {@link OffsetScrollPositionArgumentResolver} to post-process {@link OffsetScrollPosition}.
29+
* {@link MethodParameter}. A {@link OffsetScrollPositionArgumentResolver} can either resolve
30+
* {@link OffsetScrollPosition} itself or wrap another {@link OffsetScrollPositionArgumentResolver} to post-process
31+
* {@link OffsetScrollPosition}.
3232
*
33-
* @since 3.2
3433
* @author Yanming Zhou
35-
* @see HandlerMethodArgumentResolver
34+
* @author Mark Paluch
35+
* @since 3.2
36+
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver
3637
*/
3738
public interface OffsetScrollPositionArgumentResolver extends HandlerMethodArgumentResolver {
3839

3940
/**
40-
* Resolves a {@link OffsetScrollPosition} method parameter into an argument value from a given request.
41+
* Resolves a {@link OffsetScrollPosition} method parameter into an argument value from a given request. Supports also
42+
* wrapped arguments in {@link java.util.Optional}.
4143
*
4244
* @param parameter the method parameter to resolve. This parameter must have previously been passed to
4345
* {@link #supportsParameter} which must have returned {@code true}.
4446
* @param mavContainer the ModelAndViewContainer for the current request
4547
* @param webRequest the current request
4648
* @param binderFactory a factory for creating {@link WebDataBinder} instances
47-
* @return the resolved argument value
49+
* @return the resolved argument value or {@literal null} if the value cannot be resolved. The returned value
50+
* considers {@link MethodParameter#isOptional() Optional} wrapping by returing either the value wrapped
51+
* within Optional or Optional.empty().
4852
*/
49-
@NonNull
5053
@Override
51-
OffsetScrollPosition resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
54+
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
5255
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory);
5356
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2023 the original author or authors.
2+
* Copyright 2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.web;
1717

18+
import java.util.Arrays;
19+
1820
import org.springframework.core.MethodParameter;
1921
import org.springframework.data.domain.OffsetScrollPosition;
2022
import org.springframework.lang.Nullable;
@@ -23,27 +25,28 @@
2325
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
2426
import org.springframework.web.method.support.ModelAndViewContainer;
2527

26-
import java.util.Arrays;
27-
2828
/**
29-
* {@link HandlerMethodArgumentResolver} to automatically create {@link OffsetScrollPosition} instances from request parameters.
29+
* {@link HandlerMethodArgumentResolver} to automatically create {@link OffsetScrollPosition} instances from request
30+
* parameters.
3031
*
31-
* @since 3.2
3232
* @author Yanming Zhou
33+
* @since 3.2
3334
*/
3435
public class OffsetScrollPositionHandlerMethodArgumentResolver extends OffsetScrollPositionHandlerMethodArgumentResolverSupport
3536
implements OffsetScrollPositionArgumentResolver {
3637

3738
@Override
3839
public boolean supportsParameter(MethodParameter parameter) {
39-
return OffsetScrollPosition.class.equals(parameter.getParameterType());
40+
return OffsetScrollPosition.class.equals(parameter.nestedIfOptional().getNestedParameterType());
4041
}
4142

4243
@Override
43-
public OffsetScrollPosition resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
44+
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
4445
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) {
4546

46-
String[] offsetParameter = webRequest.getParameterValues(getOffsetParameter(parameter));
47-
return parseParameterIntoOffsetScrollPosition(offsetParameter != null ? Arrays.asList(offsetParameter) : null);
47+
String[] offsetParameter = webRequest.getParameterValues(getOffsetParameter(parameter.nestedIfOptional()));
48+
return adaptArgumentIfNecessary(
49+
parseParameterIntoOffsetScrollPosition(offsetParameter != null ? Arrays.asList(offsetParameter) : null),
50+
parameter);
4851
}
4952
}

src/main/java/org/springframework/data/web/OffsetScrollPositionHandlerMethodArgumentResolverSupport.java

+33-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,22 +15,23 @@
1515
*/
1616
package org.springframework.data.web;
1717

18+
import java.util.List;
19+
import java.util.Optional;
20+
1821
import org.springframework.core.MethodParameter;
1922
import org.springframework.data.domain.OffsetScrollPosition;
2023
import org.springframework.data.domain.ScrollPosition;
2124
import org.springframework.lang.Nullable;
2225
import org.springframework.util.Assert;
26+
import org.springframework.util.CollectionUtils;
2327
import org.springframework.util.StringUtils;
2428

25-
import java.util.List;
26-
import java.util.Objects;
27-
2829
/**
29-
* Base class providing methods for handler method argument resolvers to create {@link OffsetScrollPosition} instances from request
30-
* parameters.
30+
* Base class providing methods for handler method argument resolvers to create {@link OffsetScrollPosition} instances
31+
* from request parameters.
3132
*
32-
* @since 3.2
3333
* @author Yanming Zhou
34+
* @since 3.2
3435
* @see OffsetScrollPositionHandlerMethodArgumentResolver
3536
* @see ReactiveOffsetScrollPositionHandlerMethodArgumentResolver
3637
*/
@@ -71,7 +72,7 @@ public void setQualifierDelimiter(@Nullable String qualifierDelimiter) {
7172
* @param parameter can be {@literal null}.
7273
* @return the offset parameter
7374
*/
74-
protected String getOffsetParameter(@Nullable MethodParameter parameter) {
75+
protected String getOffsetParameter(MethodParameter parameter) {
7576

7677
StringBuilder builder = new StringBuilder();
7778

@@ -89,19 +90,39 @@ protected String getOffsetParameter(@Nullable MethodParameter parameter) {
8990
* Parses the given source into a {@link OffsetScrollPosition} instance.
9091
*
9192
* @param source could be {@literal null} or empty.
92-
* @return parsed OffsetScrollPosition
93+
* @return parsed OffsetScrollPosition or {@literal null} if it cannot be constructed.
9394
*/
95+
@Nullable
9496
OffsetScrollPosition parseParameterIntoOffsetScrollPosition(@Nullable List<String> source) {
97+
9598
// No parameter or Single empty parameter, e.g "offset="
96-
if (source == null || source.size() == 1 && !StringUtils.hasText(source.get(0))) {
97-
return ScrollPosition.offset();
99+
if (CollectionUtils.isEmpty(source) || (source.size() == 1 && !StringUtils.hasText(source.get(0)))) {
100+
return null;
98101
}
102+
99103
try {
100104
long offset = Long.parseLong(source.get(0));
101105
return ScrollPosition.offset(offset);
102106
} catch (NumberFormatException ex) {
103-
return ScrollPosition.offset();
107+
return null;
104108
}
105109
}
106110

111+
/**
112+
* Adapt the given argument against the method parameter, if necessary.
113+
*
114+
* @param arg the resolved argument.
115+
* @param parameter the method parameter descriptor.
116+
* @return the adapted argument, or the original resolved argument as-is.
117+
*/
118+
@Nullable
119+
Object adaptArgumentIfNecessary(@Nullable Object arg, MethodParameter parameter) {
120+
121+
if (parameter.getParameterType() == Optional.class) {
122+
return arg == null ? Optional.empty() : Optional.of(arg);
123+
}
124+
125+
return arg;
126+
}
127+
107128
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,37 +15,36 @@
1515
*/
1616
package org.springframework.data.web;
1717

18+
import java.util.List;
19+
1820
import org.springframework.core.MethodParameter;
1921
import org.springframework.data.domain.OffsetScrollPosition;
20-
import org.springframework.lang.NonNull;
2122
import org.springframework.web.reactive.BindingContext;
2223
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
2324
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
2425
import org.springframework.web.server.ServerWebExchange;
2526

26-
import java.util.List;
27-
2827
/**
29-
* Reactive {@link HandlerMethodArgumentResolver} to create {@link OffsetScrollPosition} instances from query string parameters.
28+
* Reactive {@link HandlerMethodArgumentResolver} to create {@link OffsetScrollPosition} instances from query string
29+
* parameters.
3030
*
31-
* @since 3.2
3231
* @author Yanming Zhou
32+
* @since 3.2
3333
*/
34-
public class ReactiveOffsetScrollPositionHandlerMethodArgumentResolver extends OffsetScrollPositionHandlerMethodArgumentResolverSupport
35-
implements SyncHandlerMethodArgumentResolver {
34+
public class ReactiveOffsetScrollPositionHandlerMethodArgumentResolver
35+
extends OffsetScrollPositionHandlerMethodArgumentResolverSupport implements SyncHandlerMethodArgumentResolver {
3636

3737
@Override
3838
public boolean supportsParameter(MethodParameter parameter) {
39-
return OffsetScrollPosition.class.equals(parameter.getParameterType());
39+
return OffsetScrollPosition.class.equals(parameter.nestedIfOptional().getNestedParameterType());
4040
}
4141

42-
@NonNull
4342
@Override
44-
public OffsetScrollPosition resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext,
43+
public Object resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext,
4544
ServerWebExchange exchange) {
4645

4746
List<String> offsetParameter = exchange.getRequest().getQueryParams().get(getOffsetParameter(parameter));
4847

49-
return parseParameterIntoOffsetScrollPosition(offsetParameter);
48+
return adaptArgumentIfNecessary(parseParameterIntoOffsetScrollPosition(offsetParameter), parameter);
5049
}
5150
}

0 commit comments

Comments
 (0)