From 28b3221bcfd1f48e0c6f392e1a8a97b9d7e82f9b Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 11 Jun 2014 10:11:39 +0200 Subject: [PATCH] DATACMNS-519 - PagedResourcesAssembler now keeps template variables of base link. Significant overhaul of the link creation in PagedResourcesAssembler. --- ...PageableHandlerMethodArgumentResolver.java | 11 ++++ .../data/web/PagedResourcesAssembler.java | 60 +++++++++++-------- .../web/PagedResourcesAssemblerUnitTests.java | 15 +++++ 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/springframework/data/web/PageableHandlerMethodArgumentResolver.java b/src/main/java/org/springframework/data/web/PageableHandlerMethodArgumentResolver.java index b4b6559e4..6ef5ac48e 100644 --- a/src/main/java/org/springframework/data/web/PageableHandlerMethodArgumentResolver.java +++ b/src/main/java/org/springframework/data/web/PageableHandlerMethodArgumentResolver.java @@ -92,6 +92,17 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum this.fallbackPageable = fallbackPageable; } + /** + * Returns whether the given {@link Pageable} is the fallback one. + * + * @param pageable + * @since 1.9 + * @return + */ + public boolean isFallbackPageable(Pageable pageable) { + return this.fallbackPageable.equals(pageable); + } + /** * Configures the maximum page size to be accepted. This allows to put an upper boundary of the page size to prevent * potential attacks trying to issue an {@link OutOfMemoryError}. Defaults to {@link #DEFAULT_MAX_PAGE_SIZE}. diff --git a/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java b/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java index 669e73cea..2d3f1a090 100644 --- a/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java +++ b/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java @@ -122,14 +122,7 @@ public class PagedResourcesAssembler implements ResourceAssembler, Pa public Link appendPaginationParameterTemplates(Link link) { Assert.notNull(link, "Link must not be null!"); - - String uri = link.getHref(); - UriTemplate uriTemplate = new UriTemplate(uri); - UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri).build(); - - TemplateVariables variables = pageableResolver.getPaginationTemplateVariables(getMethodParameter(), uriComponents); - - return new Link(uriTemplate.with(variables), link.getRel()); + return createLink(new UriTemplate(link.getHref()), null, link.getRel()); } private PagedResources createResource(Page page, @@ -144,35 +137,52 @@ public class PagedResourcesAssembler implements ResourceAssembler, Pa resources.add(assembler.toResource(element)); } + UriTemplate base = new UriTemplate(link == null ? getDefaultUriString() : link.getHref()); + PagedResources pagedResources = new PagedResources(resources, asPageMetadata(page)); - return addPaginationLinks(pagedResources, page, link == null ? getDefaultUriString().toUriString() : link.getHref()); - } - - private UriComponents getDefaultUriString() { - return baseUri == null ? ServletUriComponentsBuilder.fromCurrentRequest().build() : baseUri; - } - - private PagedResources addPaginationLinks(PagedResources resources, Page page, - String uri) { + pagedResources.add(createLink(base, null, Link.REL_SELF)); if (page.hasNext()) { - foo(resources, page.nextPageable(), uri, Link.REL_NEXT); + pagedResources.add(createLink(base, page.nextPageable(), Link.REL_NEXT)); } if (page.hasPrevious()) { - foo(resources, page.previousPageable(), uri, Link.REL_PREVIOUS); + pagedResources.add(createLink(base, page.previousPageable(), Link.REL_PREVIOUS)); } - resources.add(appendPaginationParameterTemplates(new Link(uri))); - - return resources; + return pagedResources; } - private void foo(PagedResources resources, Pageable pageable, String uri, String rel) { + /** + * Returns a default URI string either from the one configured on assembler creatino or by looking it up from the + * current request. + * + * @return + */ + private String getDefaultUriString() { + return baseUri == null ? ServletUriComponentsBuilder.fromCurrentRequest().build().toString() : baseUri.toString(); + } - UriComponentsBuilder builder = fromUriString(uri); + /** + * Creates a {@link Link} with the given rel that will be based on the given {@link UriTemplate} but enriched with the + * values of the given {@link Pageable} (if not {@literal null}) and the missing parameters added as template + * variables. + * + * @param base must not be {@literal null}. + * @param pageable can be {@literal null} + * @param rel must not be {@literal null} or empty. + * @return + */ + private Link createLink(UriTemplate base, Pageable pageable, String rel) { + + UriComponentsBuilder builder = fromUri(base.expand()); pageableResolver.enhance(builder, getMethodParameter(), pageable); - resources.add(new Link(builder.build().toUriString(), rel)); + + UriComponents components = builder.build(); + TemplateVariables variables = new TemplateVariables(base.getVariables()); + variables = variables.concat(pageableResolver.getPaginationTemplateVariables(getMethodParameter(), components)); + + return new Link(new UriTemplate(components.toString()).with(variables), rel); } /** diff --git a/src/test/java/org/springframework/data/web/PagedResourcesAssemblerUnitTests.java b/src/test/java/org/springframework/data/web/PagedResourcesAssemblerUnitTests.java index 82723cdb7..9876dd34b 100644 --- a/src/test/java/org/springframework/data/web/PagedResourcesAssemblerUnitTests.java +++ b/src/test/java/org/springframework/data/web/PagedResourcesAssemblerUnitTests.java @@ -168,6 +168,21 @@ public class PagedResourcesAssemblerUnitTests { assertThat(assembler.appendPaginationParameterTemplates(link), is(new Link("/foo?page=0{&size,sort}"))); } + /** + * @see DATACMNS-519 + */ + @Test + public void keepsExistingTemplateVariablesFromBaseLink() { + + PagedResourcesAssembler assembler = new PagedResourcesAssembler(resolver, null); + + Link link = new Link("/foo?page=0{&projection}"); + Link result = assembler.appendPaginationParameterTemplates(link); + + assertThat(result.getVariableNames(), hasSize(3)); + assertThat(result.getVariableNames(), hasItems("projection", "size", "sort")); + } + private static Page createPage(int index) { AbstractPageRequest request = new PageRequest(index, 1);