From 519f0a812c9077a4e29be790d037f8e56659fec7 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Tue, 20 Feb 2018 15:30:11 +0100 Subject: [PATCH] [DS-3489] added the facetLimit property to the buildFacetQueries for dates, reversed the order of the returned list to show the oldest pair first --- .../org/dspace/discovery/DiscoverQuery.java | 12 ++-- .../configuration/DiscoverySearchFilter.java | 4 +- .../app/rest/DiscoveryRestController.java | 7 ++- .../app/rest/RestResourceController.java | 2 +- .../DiscoverConfigurationConverter.java | 24 ++++--- .../DiscoverFacetConfigurationConverter.java | 1 + .../dspace/app/rest/link/HalLinkService.java | 2 +- ...etConfigurationResourceHalLinkFactory.java | 2 +- .../SearchResultsResourceHalLinkFactory.java | 22 +++---- .../search/SearchSupportHalLinkFactory.java | 2 +- .../rest/model/SearchConfigurationRest.java | 7 +-- .../rest/model/hateoas/DSpaceResource.java | 7 ++- .../app/rest/model/hateoas/EmbeddedPage.java | 22 ++++--- .../app/rest/model/hateoas/HALResource.java | 4 +- .../model/hateoas/SearchResultsResource.java | 26 ++++---- .../app/rest/DiscoveryRestControllerIT.java | 62 +++++++++---------- .../app/rest/matcher/FacetEntryMatcher.java | 4 ++ dspace/config/spring/api/discovery.xml | 8 ++- 18 files changed, 118 insertions(+), 100 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java index 399cde18d7..94a41f6195 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java @@ -9,6 +9,7 @@ package org.dspace.discovery; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -330,7 +331,6 @@ public class DiscoverQuery { // Example: 2001 and a gap from 10 we need the following result: 2010 - 2000 ; 2000 - 1990 hence the top // year int topYear = getTopYear(newestYear, gap); - if (gap == 1) { //We need a list of our years //We have a date range add faceting for our field @@ -338,7 +338,8 @@ public class DiscoverQuery { this.addFacetField(new DiscoverFacetField(facet.getIndexFieldName(), facet.getType(), 10, facet.getSortOrderSidebar())); } else { - List facetQueries = buildFacetQueriesWithGap(newestYear, oldestYear, dateFacet, gap, topYear); + List facetQueries = buildFacetQueriesWithGap(newestYear, oldestYear, dateFacet, gap, topYear, + facet.getFacetLimit()); for (String facetQuery : CollectionUtils.emptyIfNull(facetQueries)) { this.addFacetQuery(facetQuery); } @@ -347,10 +348,9 @@ public class DiscoverQuery { } private List buildFacetQueriesWithGap(int newestYear, int oldestYear, String dateFacet, int gap, - int topYear) { + int topYear, int facetLimit) { List facetQueries = new LinkedList<>(); - //Create facet queries but limit them to 11 (11 == when we need to show a "show more" url) - for (int year = topYear; year > oldestYear && (facetQueries.size() < 11); year -= gap) { + for (int year = topYear; year > oldestYear && (facetQueries.size() < facetLimit); year -= gap) { //Add a filter to remove the last year only if we aren't the last year int bottomYear = year - gap; //Make sure we don't go below our last year found @@ -368,10 +368,12 @@ public class DiscoverQuery { } facetQueries.add(dateFacet + ":[" + bottomYear + " TO " + currentTop + "]"); } + Collections.reverse(facetQueries); return facetQueries; } private int getTopYear(int newestYear, int gap) { return (int) (Math.ceil((float) (newestYear) / gap) * gap); } + } diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySearchFilter.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySearchFilter.java index 6820d84568..f7d4159bb2 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySearchFilter.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySearchFilter.java @@ -62,11 +62,11 @@ public class DiscoverySearchFilter { return FILTER_TYPE_DEFAULT; } - public boolean isOpenByDefault(){ + public boolean isOpenByDefault() { return isOpenByDefault; } - public void setIsOpenByDefault(boolean isOpenByDefault){ + public void setIsOpenByDefault(boolean isOpenByDefault) { this.isOpenByDefault = isOpenByDefault; } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/DiscoveryRestController.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/DiscoveryRestController.java index c966d4511b..8c10e590b0 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/DiscoveryRestController.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/DiscoveryRestController.java @@ -145,7 +145,7 @@ public class DiscoveryRestController implements InitializingBean { .getSearchObjects(query, dsoType, dsoScope, configurationName, searchFilters, page); //Convert the Search JSON results to paginated HAL resources - SearchResultsResource searchResultsResource = new SearchResultsResource(searchResultsRest, utils); + SearchResultsResource searchResultsResource = new SearchResultsResource(searchResultsRest, utils, page); halLinkService.addLinks(searchResultsResource, page); return searchResultsResource; } @@ -153,7 +153,8 @@ public class DiscoveryRestController implements InitializingBean { @RequestMapping(method = RequestMethod.GET, value = "/facets") public FacetConfigurationResource getFacetsConfiguration( @RequestParam(name = "scope", required = false) String dsoScope, - @RequestParam(name = "configuration", required = false) String configurationName) throws Exception { + @RequestParam(name = "configuration", required = false) String configurationName, + Pageable pageable) throws Exception { if (log.isTraceEnabled()) { log.trace("Retrieving facet configuration for scope " + StringUtils.trimToEmpty(dsoScope) + " and configuration name " + StringUtils.trimToEmpty(configurationName)); @@ -163,7 +164,7 @@ public class DiscoveryRestController implements InitializingBean { .getFacetsConfiguration(dsoScope, configurationName); FacetConfigurationResource facetConfigurationResource = new FacetConfigurationResource(facetConfigurationRest); - halLinkService.addLinks(facetConfigurationResource); + halLinkService.addLinks(facetConfigurationResource, pageable); return facetConfigurationResource; } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java index 71623199cb..dba8e4506a 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java @@ -707,7 +707,7 @@ public class RestResourceController implements InitializingBean { // if we really want to implement pagination we should implement a // link repository so to fall in the previous block code EmbeddedPage ep = (EmbeddedPage) resource.getEmbeddedResources().get(rel); - List fullList = ep.getFullList(); + List fullList = ep.getFullList().get(rel); if (fullList == null || fullList.size() == 0) { return null; } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverConfigurationConverter.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverConfigurationConverter.java index 8331b35be4..31e271a5af 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverConfigurationConverter.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverConfigurationConverter.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.StringUtils; import org.dspace.app.rest.model.SearchConfigurationRest; import org.dspace.discovery.configuration.DiscoveryConfiguration; import org.dspace.discovery.configuration.DiscoverySearchFilter; @@ -29,7 +28,8 @@ public class DiscoverConfigurationConverter { public SearchConfigurationRest convert(DiscoveryConfiguration configuration) { SearchConfigurationRest searchConfigurationRest = new SearchConfigurationRest(); if (configuration != null) { - addSearchFilters(searchConfigurationRest, configuration.getSearchFilters(), configuration.getSidebarFacets()); + addSearchFilters(searchConfigurationRest, + configuration.getSearchFilters(), configuration.getSidebarFacets()); addSortOptions(searchConfigurationRest, configuration.getSearchSortConfiguration()); setDefaultSortOption(configuration, searchConfigurationRest); } @@ -53,18 +53,22 @@ public class DiscoverConfigurationConverter { } - public void addSearchFilters(SearchConfigurationRest searchConfigurationRest, List searchFilterList, List facetList){ - List facetFieldNames = facetList.stream().map(DiscoverySearchFilterFacet::getIndexFieldName).collect(Collectors.toList()); - for(DiscoverySearchFilter discoverySearchFilter : CollectionUtils.emptyIfNull(searchFilterList)){ - SearchConfigurationRest.Filter filter = new SearchConfigurationRest.Filter(); - filter.setFilter(discoverySearchFilter.getIndexFieldName());if(facetFieldNames.stream().anyMatch(str -> str.equals(discoverySearchFilter.getIndexFieldName()))){ + public void addSearchFilters(SearchConfigurationRest searchConfigurationRest, + List searchFilterList, + List facetList) { + List facetFieldNames = facetList.stream().map(DiscoverySearchFilterFacet::getIndexFieldName) + .collect(Collectors.toList()); + for (DiscoverySearchFilter discoverySearchFilter : CollectionUtils.emptyIfNull(searchFilterList)) { + SearchConfigurationRest.Filter filter = new SearchConfigurationRest.Filter(); + filter.setFilter(discoverySearchFilter.getIndexFieldName()); + if (facetFieldNames.stream().anyMatch(str -> str.equals(discoverySearchFilter.getIndexFieldName()))) { filter.setHasFacets(true); } filter.setType(discoverySearchFilter.getType()); filter.setOpenByDefault(discoverySearchFilter.isOpenByDefault()); - filter.addDefaultOperatorsToList(); - searchConfigurationRest.addFilter(filter); - } + filter.addDefaultOperatorsToList(); + searchConfigurationRest.addFilter(filter); + } } private void addSortOptions(SearchConfigurationRest searchConfigurationRest, diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverFacetConfigurationConverter.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverFacetConfigurationConverter.java index 60d8f94d2f..b8495db794 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverFacetConfigurationConverter.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverFacetConfigurationConverter.java @@ -41,6 +41,7 @@ public class DiscoverFacetConfigurationConverter { SearchFacetEntryRest facetEntry = new SearchFacetEntryRest(discoverySearchFilterFacet.getIndexFieldName()); facetEntry.setFacetType(discoverySearchFilterFacet.getType()); + facetEntry.setFacetLimit(discoverySearchFilterFacet.getFacetLimit()); facetConfigurationRest.addSidebarFacet(facetEntry); } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/HalLinkService.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/HalLinkService.java index 874b4a6e44..935afd45a6 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/HalLinkService.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/HalLinkService.java @@ -65,7 +65,7 @@ public class HalLinkService { } } } else if (obj instanceof EmbeddedPage) { - for (Object subObj : ((EmbeddedPage) obj).getPageContent()) { + for (Object subObj : ((EmbeddedPage) obj).getPageContent().values()) { if (subObj instanceof HALResource) { addLinks((HALResource) subObj); } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/FacetConfigurationResourceHalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/FacetConfigurationResourceHalLinkFactory.java index f0cdb99d04..f66df9350e 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/FacetConfigurationResourceHalLinkFactory.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/FacetConfigurationResourceHalLinkFactory.java @@ -32,7 +32,7 @@ public class FacetConfigurationResourceHalLinkFactory extends DiscoveryRestHalLi if (data != null) { list.add(buildLink(Link.REL_SELF, getMethodOn() - .getFacetsConfiguration(data.getScope(), data.getConfigurationName()))); + .getFacetsConfiguration(data.getScope(), data.getConfigurationName(), page))); } } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchResultsResourceHalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchResultsResourceHalLinkFactory.java index cb283583dc..5da68831d4 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchResultsResourceHalLinkFactory.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchResultsResourceHalLinkFactory.java @@ -9,14 +9,11 @@ package org.dspace.app.rest.link.search; import java.util.LinkedList; -import org.dspace.app.rest.model.SearchResultsRest; -import org.dspace.app.rest.model.hateoas.EmbeddedPageHeader; -import org.dspace.app.rest.model.hateoas.SearchResultEntryResource; import org.dspace.app.rest.model.hateoas.SearchResultsResource; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.hateoas.Link; import org.springframework.stereotype.Component; +import org.springframework.web.util.UriComponentsBuilder; /** * This class will add links to the SearchResultsResource. This method will be called when calling the higher up @@ -27,15 +24,16 @@ public class SearchResultsResourceHalLinkFactory extends DiscoveryRestHalLinkFac protected void addLinks(SearchResultsResource halResource, Pageable pageable, LinkedList list) throws Exception { - SearchResultsRest data = halResource.getContent(); + UriComponentsBuilder uriBuilder = uriBuilder(getMethodOn() + .getSearchObjects(halResource.getContent().getQuery(), + halResource.getContent().getDsoType(), + halResource.getContent().getScope(), + halResource.getContent() + .getConfigurationName(), + halResource.getContent().getSearchFilters(), + null)); + list.add(buildLink(Link.REL_SELF, uriBuilder.build().toUriString())); - if (data != null && pageable != null) { - PageImpl page = new PageImpl( - halResource.getEntryResources(), - pageable, data.getTotalNumberOfResults()); - - halResource.setPageHeader(new EmbeddedPageHeader(buildSearchBaseLink(data), page)); - } } @Override diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchSupportHalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchSupportHalLinkFactory.java index f8e533c0cf..e253781d2d 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchSupportHalLinkFactory.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchSupportHalLinkFactory.java @@ -29,7 +29,7 @@ public class SearchSupportHalLinkFactory extends HalLinkFactory getResourceClass() { diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchConfigurationRest.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchConfigurationRest.java index d4eefd28b0..fa0bda97e1 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchConfigurationRest.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchConfigurationRest.java @@ -11,7 +11,6 @@ import java.util.LinkedList; import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.dspace.app.rest.DiscoveryRestController; @@ -117,10 +116,10 @@ public class SearchConfigurationRest extends BaseObjectRest { public static final String OPERATOR_CONTAINS = "contains"; public static final String OPERATOR_NOTCONTAINS = "notcontains"; - public boolean isHasFacets(){ + public boolean isHasFacets() { return hasFacets; } - public void setHasFacets(boolean hasFacets){ + public void setHasFacets(boolean hasFacets) { this.hasFacets = hasFacets; } @@ -180,7 +179,7 @@ public class SearchConfigurationRest extends BaseObjectRest { .append(operators) .toHashCode(); } - public static class Operator{ + public static class Operator { private String operator; public Operator(String operator) { diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/DSpaceResource.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/DSpaceResource.java index a14bf71eef..d979d4c28b 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/DSpaceResource.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/DSpaceResource.java @@ -69,7 +69,8 @@ public abstract class DSpaceResource extends HAL // TODO add support for single linked object other than for collections Page pageResult = (Page) m .invoke(linkRepository, null, ((BaseObjectRest) data).getId(), null, null); - EmbeddedPage ep = new EmbeddedPage(linkToSubResource.getHref(), pageResult, null); + EmbeddedPage ep = new EmbeddedPage(linkToSubResource.getHref(), pageResult, + null, name); embedded.put(name, ep); found = true; } @@ -125,7 +126,7 @@ public abstract class DSpaceResource extends HAL PageImpl page = new PageImpl(linkedRMList); wrapObject = new EmbeddedPage(linkToSubResource.getHref(), page.map(resourceRepository::wrapResource), - linkedRMList); + linkedRMList, name); } else { wrapObject = null; } @@ -150,7 +151,7 @@ public abstract class DSpaceResource extends HAL .invoke(linkRepository, null, ((BaseObjectRest) data).getId(), null, null); EmbeddedPage ep = new EmbeddedPage(linkToSubResource.getHref(), - pageResult, null); + pageResult, null, name); embedded.put(name, ep); } else { RestAddressableModel object = (RestAddressableModel) m diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/EmbeddedPage.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/EmbeddedPage.java index f30f5f5f7d..a893369a5a 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/EmbeddedPage.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/EmbeddedPage.java @@ -7,7 +7,9 @@ */ package org.dspace.app.rest.model.hateoas; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -18,25 +20,27 @@ import org.springframework.data.domain.Page; */ public class EmbeddedPage extends EmbeddedPageHeader { - private List fullList; + //TODO Make map get relation name from constructor + private Map fullMap; - public EmbeddedPage(String self, Page page, List fullList) { - this(self, page, fullList, true); + public EmbeddedPage(String self, Page page, List fullList, String relation) { + this(self, page, fullList, true, relation); } - public EmbeddedPage(String self, Page page, List fullList, boolean totalElementsIsKnown) { + public EmbeddedPage(String self, Page page, List fullList, boolean totalElementsIsKnown, String relation) { super(self, page, totalElementsIsKnown); - this.fullList = fullList; + fullMap = new HashMap(); + fullMap.put(relation, fullList); } @JsonProperty(value = "_embedded") - public List getPageContent() { - return page.getContent(); + public Map getPageContent() { + return fullMap; } @JsonIgnore - public List getFullList() { - return fullList; + public Map getFullList() { + return fullMap; } } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/HALResource.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/HALResource.java index 360f558fef..207aa2713b 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/HALResource.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/HALResource.java @@ -40,7 +40,9 @@ public abstract class HALResource extends Resource { public void embedResource(String relationship, HALResource resource) { embedded.put(relationship, resource); } - + public void embedResource(String relationship, EmbeddedPage embeddedPage) { + embedded.put(relationship, embeddedPage); + } public void embedResource(String relationship, Collection resource) { embedded.put(relationship, resource); } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/SearchResultsResource.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/SearchResultsResource.java index 9102152b38..0478031b66 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/SearchResultsResource.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/SearchResultsResource.java @@ -17,6 +17,9 @@ import org.dspace.app.rest.model.SearchResultEntryRest; import org.dspace.app.rest.model.SearchResultsRest; import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource; import org.dspace.app.rest.utils.Utils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; /** * This class' purpose is to create a container with a list of the SearchResultEntryResources @@ -27,22 +30,16 @@ public class SearchResultsResource extends HALResource { @JsonIgnore private List entryResources; - public SearchResultsResource(final SearchResultsRest data, final Utils utils) { + public SearchResultsResource(final SearchResultsRest data, final Utils utils, Pageable pageable) { super(data); + addEmbeds(data, utils, pageable); - addEmbeds(data, utils); } - - public List getEntryResources() { - return entryResources; - } - - private void addEmbeds(final SearchResultsRest data, final Utils utils) { - embedSearchResults(data, utils); + private void addEmbeds(final SearchResultsRest data, final Utils utils, Pageable pageable) { + embedSearchResults(data, utils, pageable); embedFacetResults(data); } - private void embedFacetResults(final SearchResultsRest data) { List facetResources = new LinkedList<>(); for (SearchFacetEntryRest searchFacetEntryRest : CollectionUtils.emptyIfNull(data.getFacets())) { @@ -51,14 +48,13 @@ public class SearchResultsResource extends HALResource { embedResource("facets", facetResources); } - - private void embedSearchResults(final SearchResultsRest data, final Utils utils) { + private void embedSearchResults(final SearchResultsRest data, final Utils utils, Pageable pageable) { entryResources = new LinkedList<>(); for (SearchResultEntryRest searchResultEntry : CollectionUtils.emptyIfNull(data.getSearchResults())) { entryResources.add(new SearchResultEntryResource(searchResultEntry, utils)); } - - embedResource("objects", entryResources); + Page page = new PageImpl<>(entryResources, pageable, data.getTotalNumberOfResults()); + EmbeddedPage embeddedPage = new EmbeddedPage("objects", page, entryResources, "objects"); + embedResource("searchResult", embeddedPage); } - } diff --git a/dspace-spring-rest/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java b/dspace-spring-rest/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java index 9e314bf887..e042ca9b05 100644 --- a/dspace-spring-rest/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java +++ b/dspace-spring-rest/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java @@ -819,13 +819,13 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest .andExpect(jsonPath("$.type", is("discover"))) //There needs to be a page object that shows the total pages and total elements as well as the // size and the current page (number) - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7) ))) //These search results have to be shown in the embedded.objects section as these are the items // given in the structure defined above. //Seeing as everything fits onto one page, they have to all be present - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"), //This has to be like this because collections don't have anything else @@ -901,12 +901,12 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The page object has to look like this because we've only made 7 elements, the default size is 20 // and they all fit onto one page (20 > 7) so totalPages has to be 1. Number is 0 because //page 0 is the default page we view if not specified otherwise - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7) ))) //All elements have to be present in the embedded.objects section, these are the ones we made in // the structure defined above - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"), //Match without any parameters because collections don't have anything special to check in the @@ -990,11 +990,11 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest .andExpect(jsonPath("$.type", is("discover"))) //The page object has to look like this because we've only made 7 items, they all fit onto 1 page // because the default size is 20 and the default starting page is 0. - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7) ))) //All the elements created in the structure above have to be present in the embedded.objects section - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"), //Collections are specified like this because they don't have any special properties @@ -1070,12 +1070,12 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest .andExpect(jsonPath("$.type", is("discover"))) //The page object has to look like this because of the query we specified, only two elements match // the query. - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 2) ))) //Only the two item elements match the query, therefore those are the only ones that can be in the // embedded.objects section - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match("item", "items"), SearchResultMatcher.match("item", "items") ))) @@ -1148,13 +1148,13 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The type has to be 'discover' .andExpect(jsonPath("$.type", is("discover"))) //The page element has to look like this because it contains all the elements we've just created - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7) ))) //The scope property has to be set to the value we entered in the parameters .andExpect(jsonPath("$.scope", is("test"))) //All the elements created in the structure above have to be present in the embedded.objects section - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"), //Collections are specified like this because they don't have any special properties @@ -1230,12 +1230,12 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest .andExpect(jsonPath("$.type", is("discover"))) //The page element needs to look like this and only have three totalElements because we only want // the items (dsoType) and we only created three items - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3) ))) //Only the three items can be present in the embedded.objects section as that's what we specified // in the dsoType parameter - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match("item", "items"), SearchResultMatcher.match("item", "items"), SearchResultMatcher.match("item", "items") @@ -1307,12 +1307,12 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest .andExpect(jsonPath("$.type", is("discover"))) //The page object has to look like this and only contain three total elements because we only want // to get the items back - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3) ))) //Only the three items can be present in the embedded.objects section as that's what we specified // in the dsoType parameter - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match("item", "items"), SearchResultMatcher.match("item", "items"), SearchResultMatcher.match("item", "items") @@ -1320,7 +1320,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //Here we want to match on the item name in a certain specified order because we want to check the // sort properly //We check whether the items are sorted properly as we expected - .andExpect(jsonPath("$._embedded.objects", Matchers.contains( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.contains( SearchResultMatcher.matchOnItemName("item", "items", "Public"), SearchResultMatcher.matchOnItemName("item", "items", "Test"), SearchResultMatcher.matchOnItemName("item", "items", "Testing") @@ -1522,12 +1522,12 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //Page number 1 because that's the param we entered //TotalPages 4 because size = 2 and total elements is 7 -> 4 pages //We made 7 elements -> 7 total elements - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntryWithTotalPagesAndElements(1, 2, 4, 7) ))) //These are the two elements that'll be shown (because page = 1, so the third and fourth element // in the list) and they'll be the only ones because the size is 2 - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match(), SearchResultMatcher.match() ))) @@ -1608,11 +1608,11 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The type has to be 'discover' .andExpect(jsonPath("$.type", is("discover"))) //The page object needs to look like this - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntry(0, 20) ))) //This is the only item that should be returned with the query given - .andExpect(jsonPath("$._embedded.objects", Matchers.contains( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.contains( SearchResultMatcher.matchOnItemName("item", "items", "Test") ))) @@ -1685,11 +1685,11 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The type has to be 'discover' .andExpect(jsonPath("$.type", is("discover"))) //The page object needs to look like this - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntry(0, 20) ))) //These are the items that aren't set to private - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"), //Collections are specified like this because they don't have any special properties @@ -1699,7 +1699,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest SearchResultMatcher.matchOnItemName("item", "items", "Public item 2") ))) //This is a private item, this shouldn't show up in the result - .andExpect(jsonPath("$._embedded.objects", + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.not(SearchResultMatcher.matchOnItemName("item", "items", "Test 2")))) //These facets have to show up in the embedded.facets section as well with the given hasMore // property because we don't exceed their default limit for a hasMore true (the default is 10) @@ -1853,11 +1853,11 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The type has to be 'discover' .andExpect(jsonPath("$.type", is("discover"))) //The page object needs to look like this - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntry(0, 20) ))) //The search results have to contain the items belonging to the scope specified - .andExpect(jsonPath("$._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( SearchResultMatcher.matchOnItemName("item", "items", "Test 2"), SearchResultMatcher.matchOnItemName("item", "items", "Public item 2") ))) @@ -1929,17 +1929,17 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The type has to be 'discover' .andExpect(jsonPath("$.type", is("discover"))) //The page object needs to look like this - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntry(0, 20) ))) //Make sure that the search results contains the item with the correct scope - .andExpect(jsonPath("$._embedded.objects", Matchers.contains( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.contains( SearchResultMatcher.matchOnItemName("item", "items", "Test 2") // SearchResultMatcher.matchOnItemName("item", "items", "Public item 2") ))) //Make sure that the search result doesn't contain the item that's set to private but does have // the correct scope - .andExpect(jsonPath("$._embedded.objects", Matchers.not(Matchers.contains( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.not(Matchers.contains( SearchResultMatcher.matchOnItemName("item", "items", "Public item 2") )))) //These facets have to show up in the embedded.facets section as well with the given hasMore @@ -2006,12 +2006,12 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The type has to be 'discover' .andExpect(jsonPath("$.type", is("discover"))) //The page object needs to look like this - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntry(0, 20) ))) //The search results has to contain the item with the query in the title and the hithighlight has // to be filled in with a string containing the query - .andExpect(jsonPath("$._embedded.objects", Matchers.contains( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.contains( SearchResultMatcher .matchOnItemNameAndHitHighlight("item", "items", "Public item 2", query, "dc.title") ))) @@ -2081,11 +2081,11 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The type has to be 'discover' .andExpect(jsonPath("$.type", is("discover"))) //The page object needs to look like this - .andExpect(jsonPath("$.page", is( + .andExpect(jsonPath("$._embedded.searchResult.page", is( PageMatcher.pageEntry(0, 20) ))) //The search results should not contain this - .andExpect(jsonPath("$._embedded.objects", Matchers.not(Matchers.contains( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.not(Matchers.contains( SearchResultMatcher .matchOnItemNameAndHitHighlight("item", "items", "Public item 2", query, "dc.title") )))) diff --git a/dspace-spring-rest/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java b/dspace-spring-rest/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java index 30d34630bc..1bcca3d1cc 100644 --- a/dspace-spring-rest/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java +++ b/dspace-spring-rest/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java @@ -23,6 +23,7 @@ public class FacetEntryMatcher { return allOf( hasJsonPath("$.name", is("author")), hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", is(10)), hasJsonPath("$._links.self.href", containsString("api/discover/facets/author")), hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/author")) ); @@ -32,6 +33,7 @@ public class FacetEntryMatcher { return allOf( hasJsonPath("$.name", is("subject")), hasJsonPath("$.facetType", is("hierarchical")), + hasJsonPath("$.facetLimit", is(10)), hasJsonPath("$._links.self.href", containsString("api/discover/facets/subject")), hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/subject")) @@ -42,6 +44,7 @@ public class FacetEntryMatcher { return allOf( hasJsonPath("$.name", is("dateIssued")), hasJsonPath("$.facetType", is("date")), + hasJsonPath("$.facetLimit", is(10)), hasJsonPath("$._links.self.href", containsString("api/discover/facets/dateIssued")), hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/dateIssued")) ); @@ -51,6 +54,7 @@ public class FacetEntryMatcher { return allOf( hasJsonPath("$.name", is("has_content_in_original_bundle")), hasJsonPath("$.facetType", is("standard")), + hasJsonPath("$.facetLimit", is(2)), hasJsonPath("$._links.self.href", containsString("api/discover/facets/has_content_in_original_bundle")), hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/has_content_in_original_bundle")) ); diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 01563b9a85..9cab950db0 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -113,6 +113,7 @@ + @@ -220,6 +221,7 @@ + @@ -401,6 +403,7 @@ + @@ -429,5 +432,8 @@ - + + + +