diff --git a/src/main/java/com/restful_spring/rest_interceptor/RestInterceptor.java b/src/main/java/com/restful_spring/rest_interceptor/RestInterceptor.java index 1508245..ae37918 100644 --- a/src/main/java/com/restful_spring/rest_interceptor/RestInterceptor.java +++ b/src/main/java/com/restful_spring/rest_interceptor/RestInterceptor.java @@ -2,7 +2,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.util.List; import org.springframework.web.cors.CorsUtils; import org.springframework.web.servlet.HandlerInterceptor; @@ -17,7 +16,7 @@ */ public abstract class RestInterceptor implements HandlerInterceptor { - protected List restfulPatterns = List.of(); + protected RestfulPatterns restfulPatterns = RestfulPatterns.empty(); @Override public final boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { @@ -39,8 +38,7 @@ private boolean isPreFlightRequest(final HttpServletRequest request) { *

If request path is not matched with any of the restfulPatterns, it should be skipped. */ private boolean shouldSkip(final HttpServletRequest request) { - return this.restfulPatterns.stream() - .noneMatch(pattern -> pattern.matches(request)); + return restfulPatterns.noneMatches(request); } /** @@ -50,4 +48,16 @@ private boolean shouldSkip(final HttpServletRequest request) { protected boolean doInternal(HttpServletRequest request, HttpServletResponse response, Object handler) { return true; } + + /** + * Adds all RestfulPatterns from the given RestfulPatterns instance. + *

+ * This method merges the provided RestfulPatterns into the existing collection. + * + * @param restfulPatterns the RestfulPatterns to be added + * @since Upcoming + */ + void addRestfulPatterns(final RestfulPatterns restfulPatterns) { + this.restfulPatterns.addAll(restfulPatterns); + } } diff --git a/src/main/java/com/restful_spring/rest_interceptor/RestInterceptorRegistration.java b/src/main/java/com/restful_spring/rest_interceptor/RestInterceptorRegistration.java index b312f13..71a32c4 100644 --- a/src/main/java/com/restful_spring/rest_interceptor/RestInterceptorRegistration.java +++ b/src/main/java/com/restful_spring/rest_interceptor/RestInterceptorRegistration.java @@ -1,6 +1,5 @@ package com.restful_spring.rest_interceptor; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; @@ -34,14 +33,24 @@ public RestInterceptorRegistration addRestfulPatterns(RestfulPattern... restfulP /** * Collection-based variant of {@link #addRestfulPatterns(RestfulPattern...)}. - *

Call InterceptorRegistration's addPathPatterns method with the paths of the RestfulPatterns. */ public RestInterceptorRegistration addRestfulPatterns(Collection restfulPatterns) { - restInterceptor.restfulPatterns = new ArrayList<>(restfulPatterns); - registration.addPathPatterns(restfulPatterns.stream() - .map(RestfulPattern::getPath) - .toList() - ); + return addRestfulPatterns(RestfulPatterns.from(restfulPatterns)); + } + + /** + * Adds the given RestfulPatterns to the RestInterceptor and updates path patterns. + *

+ * This method registers the provided RestfulPatterns with the RestInterceptor and ensures that the corresponding + * paths are added to the interceptor registration. + * + * @param restfulPatterns the RestfulPatterns to be registered + * @return this RestInterceptorRegistration instance for method chaining + * @since Upcoming + */ + public RestInterceptorRegistration addRestfulPatterns(RestfulPatterns restfulPatterns) { + restInterceptor.addRestfulPatterns(restfulPatterns); + registration.addPathPatterns(restfulPatterns.getPaths()); return this; } diff --git a/src/main/java/com/restful_spring/rest_interceptor/RestfulPatterns.java b/src/main/java/com/restful_spring/rest_interceptor/RestfulPatterns.java new file mode 100644 index 0000000..7a52845 --- /dev/null +++ b/src/main/java/com/restful_spring/rest_interceptor/RestfulPatterns.java @@ -0,0 +1,77 @@ +package com.restful_spring.rest_interceptor; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * First-class collection of RestfulPattern. + *

+ * Encapsulates a Collection of RestfulPattern and provides apis. + * + * @author Dh3356 + * @since Upcoming + */ +public final class RestfulPatterns { + + private final List values; + + private RestfulPatterns(List values) { + this.values = values; + } + + /** + * Create an empty RestfulPatterns. + *

+ * Static factory method for creating a RestfulPatterns. + * + * @return an empty RestfulPatterns + */ + static RestfulPatterns empty() { + return new RestfulPatterns(new ArrayList<>()); + } + + /** + * Create a RestfulPatterns from a Collection of RestfulPattern. + *

+ * Static factory method for creating a RestfulPatterns. + * + * @param values a Collection of RestfulPattern + * @return a RestfulPatterns + */ + static RestfulPatterns from(final Collection values) { + return new RestfulPatterns(new ArrayList<>(values)); + } + + /** + * Determines whether the given request does not match any RestfulPatterns. + * + * @param request the HttpServletRequest to be checked against the patterns + * @return {@code true} if no patterns match the request, otherwise {@code false} + */ + boolean noneMatches(final HttpServletRequest request) { + return values.stream() + .noneMatch(pattern -> pattern.matches(request)); + } + + /** + * Add all RestfulPatterns from another RestfulPatterns. + * + * @param restfulPatterns another RestfulPatterns + */ + void addAll(final RestfulPatterns restfulPatterns) { + values.addAll(List.copyOf(restfulPatterns.values)); + } + + /** + * Get the paths of the RestfulPatterns. + * + * @return a List of paths + */ + List getPaths() { + return values.stream() + .map(RestfulPattern::getPath) + .toList(); + } +} diff --git a/src/test/java/com/restful_spring/rest_interceptor/RestInterceptorTest.java b/src/test/java/com/restful_spring/rest_interceptor/RestInterceptorTest.java index d1a4c4c..931bfcd 100644 --- a/src/test/java/com/restful_spring/rest_interceptor/RestInterceptorTest.java +++ b/src/test/java/com/restful_spring/rest_interceptor/RestInterceptorTest.java @@ -49,7 +49,7 @@ void preFlightRequest() { @Test void pathMatchingWithRestfulPattern() { // Given - interceptor.restfulPatterns = List.of(REGISTRATION_PATTERN); + interceptor.restfulPatterns = RestfulPatterns.from(List.of(REGISTRATION_PATTERN)); // When request.setRequestURI(FOO); @@ -63,7 +63,7 @@ void pathMatchingWithRestfulPattern() { @Test void skipWithNonMatchingPath() { // Given - interceptor.restfulPatterns = List.of(REGISTRATION_PATTERN); + interceptor.restfulPatterns = RestfulPatterns.from(List.of(REGISTRATION_PATTERN)); // When request.setRequestURI(BAR); @@ -77,7 +77,7 @@ void skipWithNonMatchingPath() { @Test void shouldSkipWhenNoPatterns() { // Given - interceptor.restfulPatterns = List.of(); + interceptor.restfulPatterns = RestfulPatterns.empty(); // When request.setRequestURI(FOO); @@ -90,7 +90,7 @@ void shouldSkipWhenNoPatterns() { @Test void doInternalCalledForMatchingRequest() { // Given - interceptor.restfulPatterns = List.of(REGISTRATION_PATTERN); + interceptor.restfulPatterns = RestfulPatterns.from(List.of(REGISTRATION_PATTERN)); // When request.setRequestURI(FOO); @@ -104,7 +104,7 @@ void doInternalCalledForMatchingRequest() { @Test void doInternalNotCalledForNonMatchingRequest() { // Given - interceptor.restfulPatterns = List.of(REGISTRATION_PATTERN); + interceptor.restfulPatterns = RestfulPatterns.from(List.of(REGISTRATION_PATTERN)); // When request.setRequestURI(BAR); diff --git a/src/test/java/com/restful_spring/rest_interceptor/RestfulPatternsTest.java b/src/test/java/com/restful_spring/rest_interceptor/RestfulPatternsTest.java new file mode 100644 index 0000000..56de071 --- /dev/null +++ b/src/test/java/com/restful_spring/rest_interceptor/RestfulPatternsTest.java @@ -0,0 +1,86 @@ +package com.restful_spring.rest_interceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.lang.reflect.Field; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpMethod; +import org.springframework.mock.web.MockHttpServletRequest; + +class RestfulPatternsTest { + + private static List parseValues(RestfulPatterns patterns) { + try { + Field valuesField = RestfulPatterns.class.getDeclaredField("values"); + valuesField.setAccessible(true); + return (List) valuesField.get(patterns); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + @Test + void emptyCreation() { + + // Given + RestfulPatterns patterns = RestfulPatterns.empty(); + + // When + List values = parseValues(patterns); + int actual = values.size(); + + // Then + assertThat(actual).isEqualTo(0); + } + + @Test + void noneMatches() { + + // Given + RestfulPattern pattern1 = RestfulPattern.of("/foo", HttpMethod.GET); + RestfulPattern pattern2 = RestfulPattern.of("/bar", HttpMethod.POST); + RestfulPatterns patterns = RestfulPatterns.from(List.of(pattern1, pattern2)); + + // When + MockHttpServletRequest request1 = new MockHttpServletRequest(HttpMethod.GET.name(), "/bar"); + MockHttpServletRequest request2 = new MockHttpServletRequest(HttpMethod.GET.name(), "/foo"); + MockHttpServletRequest request3 = new MockHttpServletRequest(HttpMethod.PATCH.name(), "/baz"); + + // Then + assertThat(patterns.noneMatches(request1)).isTrue(); + assertThat(patterns.noneMatches(request2)).isFalse(); + assertThat(patterns.noneMatches(request3)).isTrue(); + } + + @Test + void addAll() { + + // Given + RestfulPattern pattern1 = RestfulPattern.of("/foo", HttpMethod.GET); + RestfulPattern pattern2 = RestfulPattern.of("/bar", HttpMethod.POST); + RestfulPatterns patterns = RestfulPatterns.empty(); + + // When + patterns.addAll(RestfulPatterns.from(List.of(pattern1, pattern2))); + int actual = parseValues(patterns).size(); + + // Then + assertThat(actual).isEqualTo(2); + } + + @Test + void getPaths() { + + // Given + RestfulPattern pattern1 = RestfulPattern.of("/foo", HttpMethod.GET); + RestfulPattern pattern2 = RestfulPattern.of("/bar", HttpMethod.POST); + RestfulPatterns patterns = RestfulPatterns.from(List.of(pattern1, pattern2)); + + // When + List actual = patterns.getPaths(); + + // Then + assertThat(actual).containsExactlyInAnyOrder("/foo", "/bar"); + } +} \ No newline at end of file