[DS-3489] added the facetLimit property to the buildFacetQueries for dates, reversed the order of the returned list to show the oldest pair first

This commit is contained in:
Raf Ponsaerts
2018-02-20 15:30:11 +01:00
committed by Tom Desair
parent e36ded0244
commit 519f0a812c
18 changed files with 118 additions and 100 deletions

View File

@@ -9,6 +9,7 @@ package org.dspace.discovery;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedList; 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 // Example: 2001 and a gap from 10 we need the following result: 2010 - 2000 ; 2000 - 1990 hence the top
// year // year
int topYear = getTopYear(newestYear, gap); int topYear = getTopYear(newestYear, gap);
if (gap == 1) { if (gap == 1) {
//We need a list of our years //We need a list of our years
//We have a date range add faceting for our field //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, this.addFacetField(new DiscoverFacetField(facet.getIndexFieldName(), facet.getType(), 10,
facet.getSortOrderSidebar())); facet.getSortOrderSidebar()));
} else { } else {
List<String> facetQueries = buildFacetQueriesWithGap(newestYear, oldestYear, dateFacet, gap, topYear); List<String> facetQueries = buildFacetQueriesWithGap(newestYear, oldestYear, dateFacet, gap, topYear,
facet.getFacetLimit());
for (String facetQuery : CollectionUtils.emptyIfNull(facetQueries)) { for (String facetQuery : CollectionUtils.emptyIfNull(facetQueries)) {
this.addFacetQuery(facetQuery); this.addFacetQuery(facetQuery);
} }
@@ -347,10 +348,9 @@ public class DiscoverQuery {
} }
private List<String> buildFacetQueriesWithGap(int newestYear, int oldestYear, String dateFacet, int gap, private List<String> buildFacetQueriesWithGap(int newestYear, int oldestYear, String dateFacet, int gap,
int topYear) { int topYear, int facetLimit) {
List<String> facetQueries = new LinkedList<>(); List<String> 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() < facetLimit); year -= gap) {
for (int year = topYear; year > oldestYear && (facetQueries.size() < 11); year -= gap) {
//Add a filter to remove the last year only if we aren't the last year //Add a filter to remove the last year only if we aren't the last year
int bottomYear = year - gap; int bottomYear = year - gap;
//Make sure we don't go below our last year found //Make sure we don't go below our last year found
@@ -368,10 +368,12 @@ public class DiscoverQuery {
} }
facetQueries.add(dateFacet + ":[" + bottomYear + " TO " + currentTop + "]"); facetQueries.add(dateFacet + ":[" + bottomYear + " TO " + currentTop + "]");
} }
Collections.reverse(facetQueries);
return facetQueries; return facetQueries;
} }
private int getTopYear(int newestYear, int gap) { private int getTopYear(int newestYear, int gap) {
return (int) (Math.ceil((float) (newestYear) / gap) * gap); return (int) (Math.ceil((float) (newestYear) / gap) * gap);
} }
} }

View File

@@ -62,11 +62,11 @@ public class DiscoverySearchFilter {
return FILTER_TYPE_DEFAULT; return FILTER_TYPE_DEFAULT;
} }
public boolean isOpenByDefault(){ public boolean isOpenByDefault() {
return isOpenByDefault; return isOpenByDefault;
} }
public void setIsOpenByDefault(boolean isOpenByDefault){ public void setIsOpenByDefault(boolean isOpenByDefault) {
this.isOpenByDefault = isOpenByDefault; this.isOpenByDefault = isOpenByDefault;
} }

View File

@@ -145,7 +145,7 @@ public class DiscoveryRestController implements InitializingBean {
.getSearchObjects(query, dsoType, dsoScope, configurationName, searchFilters, page); .getSearchObjects(query, dsoType, dsoScope, configurationName, searchFilters, page);
//Convert the Search JSON results to paginated HAL resources //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); halLinkService.addLinks(searchResultsResource, page);
return searchResultsResource; return searchResultsResource;
} }
@@ -153,7 +153,8 @@ public class DiscoveryRestController implements InitializingBean {
@RequestMapping(method = RequestMethod.GET, value = "/facets") @RequestMapping(method = RequestMethod.GET, value = "/facets")
public FacetConfigurationResource getFacetsConfiguration( public FacetConfigurationResource getFacetsConfiguration(
@RequestParam(name = "scope", required = false) String dsoScope, @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()) { if (log.isTraceEnabled()) {
log.trace("Retrieving facet configuration for scope " + StringUtils.trimToEmpty(dsoScope) log.trace("Retrieving facet configuration for scope " + StringUtils.trimToEmpty(dsoScope)
+ " and configuration name " + StringUtils.trimToEmpty(configurationName)); + " and configuration name " + StringUtils.trimToEmpty(configurationName));
@@ -163,7 +164,7 @@ public class DiscoveryRestController implements InitializingBean {
.getFacetsConfiguration(dsoScope, configurationName); .getFacetsConfiguration(dsoScope, configurationName);
FacetConfigurationResource facetConfigurationResource = new FacetConfigurationResource(facetConfigurationRest); FacetConfigurationResource facetConfigurationResource = new FacetConfigurationResource(facetConfigurationRest);
halLinkService.addLinks(facetConfigurationResource); halLinkService.addLinks(facetConfigurationResource, pageable);
return facetConfigurationResource; return facetConfigurationResource;
} }

View File

@@ -707,7 +707,7 @@ public class RestResourceController implements InitializingBean {
// if we really want to implement pagination we should implement a // if we really want to implement pagination we should implement a
// link repository so to fall in the previous block code // link repository so to fall in the previous block code
EmbeddedPage ep = (EmbeddedPage) resource.getEmbeddedResources().get(rel); EmbeddedPage ep = (EmbeddedPage) resource.getEmbeddedResources().get(rel);
List<? extends RestAddressableModel> fullList = ep.getFullList(); List<? extends RestAddressableModel> fullList = ep.getFullList().get(rel);
if (fullList == null || fullList.size() == 0) { if (fullList == null || fullList.size() == 0) {
return null; return null;
} }

View File

@@ -11,7 +11,6 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.dspace.app.rest.model.SearchConfigurationRest; import org.dspace.app.rest.model.SearchConfigurationRest;
import org.dspace.discovery.configuration.DiscoveryConfiguration; import org.dspace.discovery.configuration.DiscoveryConfiguration;
import org.dspace.discovery.configuration.DiscoverySearchFilter; import org.dspace.discovery.configuration.DiscoverySearchFilter;
@@ -29,7 +28,8 @@ public class DiscoverConfigurationConverter {
public SearchConfigurationRest convert(DiscoveryConfiguration configuration) { public SearchConfigurationRest convert(DiscoveryConfiguration configuration) {
SearchConfigurationRest searchConfigurationRest = new SearchConfigurationRest(); SearchConfigurationRest searchConfigurationRest = new SearchConfigurationRest();
if (configuration != null) { if (configuration != null) {
addSearchFilters(searchConfigurationRest, configuration.getSearchFilters(), configuration.getSidebarFacets()); addSearchFilters(searchConfigurationRest,
configuration.getSearchFilters(), configuration.getSidebarFacets());
addSortOptions(searchConfigurationRest, configuration.getSearchSortConfiguration()); addSortOptions(searchConfigurationRest, configuration.getSearchSortConfiguration());
setDefaultSortOption(configuration, searchConfigurationRest); setDefaultSortOption(configuration, searchConfigurationRest);
} }
@@ -53,11 +53,15 @@ public class DiscoverConfigurationConverter {
} }
public void addSearchFilters(SearchConfigurationRest searchConfigurationRest, List<DiscoverySearchFilter> searchFilterList, List<DiscoverySearchFilterFacet> facetList){ public void addSearchFilters(SearchConfigurationRest searchConfigurationRest,
List<String> facetFieldNames = facetList.stream().map(DiscoverySearchFilterFacet::getIndexFieldName).collect(Collectors.toList()); List<DiscoverySearchFilter> searchFilterList,
for(DiscoverySearchFilter discoverySearchFilter : CollectionUtils.emptyIfNull(searchFilterList)){ List<DiscoverySearchFilterFacet> facetList) {
List<String> facetFieldNames = facetList.stream().map(DiscoverySearchFilterFacet::getIndexFieldName)
.collect(Collectors.toList());
for (DiscoverySearchFilter discoverySearchFilter : CollectionUtils.emptyIfNull(searchFilterList)) {
SearchConfigurationRest.Filter filter = new SearchConfigurationRest.Filter(); SearchConfigurationRest.Filter filter = new SearchConfigurationRest.Filter();
filter.setFilter(discoverySearchFilter.getIndexFieldName());if(facetFieldNames.stream().anyMatch(str -> str.equals(discoverySearchFilter.getIndexFieldName()))){ filter.setFilter(discoverySearchFilter.getIndexFieldName());
if (facetFieldNames.stream().anyMatch(str -> str.equals(discoverySearchFilter.getIndexFieldName()))) {
filter.setHasFacets(true); filter.setHasFacets(true);
} }
filter.setType(discoverySearchFilter.getType()); filter.setType(discoverySearchFilter.getType());

View File

@@ -41,6 +41,7 @@ public class DiscoverFacetConfigurationConverter {
SearchFacetEntryRest facetEntry = new SearchFacetEntryRest(discoverySearchFilterFacet.getIndexFieldName()); SearchFacetEntryRest facetEntry = new SearchFacetEntryRest(discoverySearchFilterFacet.getIndexFieldName());
facetEntry.setFacetType(discoverySearchFilterFacet.getType()); facetEntry.setFacetType(discoverySearchFilterFacet.getType());
facetEntry.setFacetLimit(discoverySearchFilterFacet.getFacetLimit());
facetConfigurationRest.addSidebarFacet(facetEntry); facetConfigurationRest.addSidebarFacet(facetEntry);
} }

View File

@@ -65,7 +65,7 @@ public class HalLinkService {
} }
} }
} else if (obj instanceof EmbeddedPage) { } else if (obj instanceof EmbeddedPage) {
for (Object subObj : ((EmbeddedPage) obj).getPageContent()) { for (Object subObj : ((EmbeddedPage) obj).getPageContent().values()) {
if (subObj instanceof HALResource) { if (subObj instanceof HALResource) {
addLinks((HALResource) subObj); addLinks((HALResource) subObj);
} }

View File

@@ -32,7 +32,7 @@ public class FacetConfigurationResourceHalLinkFactory extends DiscoveryRestHalLi
if (data != null) { if (data != null) {
list.add(buildLink(Link.REL_SELF, getMethodOn() list.add(buildLink(Link.REL_SELF, getMethodOn()
.getFacetsConfiguration(data.getScope(), data.getConfigurationName()))); .getFacetsConfiguration(data.getScope(), data.getConfigurationName(), page)));
} }
} }

View File

@@ -9,14 +9,11 @@ package org.dspace.app.rest.link.search;
import java.util.LinkedList; 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.dspace.app.rest.model.hateoas.SearchResultsResource;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link; import org.springframework.hateoas.Link;
import org.springframework.stereotype.Component; 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 * 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<Link> list) protected void addLinks(SearchResultsResource halResource, Pageable pageable, LinkedList<Link> list)
throws Exception { 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<SearchResultEntryResource> page = new PageImpl<SearchResultEntryResource>(
halResource.getEntryResources(),
pageable, data.getTotalNumberOfResults());
halResource.setPageHeader(new EmbeddedPageHeader(buildSearchBaseLink(data), page));
}
} }
@Override @Override

View File

@@ -29,7 +29,7 @@ public class SearchSupportHalLinkFactory extends HalLinkFactory<SearchSupportRes
list.add(buildLink(Link.REL_SELF, getMethodOn() list.add(buildLink(Link.REL_SELF, getMethodOn()
.getSearchSupport(null, null))); .getSearchSupport(null, null)));
list.add(buildLink("search", getMethodOn().getSearchConfiguration(null, null))); list.add(buildLink("search", getMethodOn().getSearchConfiguration(null, null)));
list.add(buildLink("facets", getMethodOn().getFacetsConfiguration(null, null))); list.add(buildLink("facets", getMethodOn().getFacetsConfiguration(null, null, pageable)));
} }
protected Class<SearchSupportResource> getResourceClass() { protected Class<SearchSupportResource> getResourceClass() {

View File

@@ -11,7 +11,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore; 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.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.dspace.app.rest.DiscoveryRestController; import org.dspace.app.rest.DiscoveryRestController;
@@ -117,10 +116,10 @@ public class SearchConfigurationRest extends BaseObjectRest<String> {
public static final String OPERATOR_CONTAINS = "contains"; public static final String OPERATOR_CONTAINS = "contains";
public static final String OPERATOR_NOTCONTAINS = "notcontains"; public static final String OPERATOR_NOTCONTAINS = "notcontains";
public boolean isHasFacets(){ public boolean isHasFacets() {
return hasFacets; return hasFacets;
} }
public void setHasFacets(boolean hasFacets){ public void setHasFacets(boolean hasFacets) {
this.hasFacets = hasFacets; this.hasFacets = hasFacets;
} }
@@ -180,7 +179,7 @@ public class SearchConfigurationRest extends BaseObjectRest<String> {
.append(operators) .append(operators)
.toHashCode(); .toHashCode();
} }
public static class Operator{ public static class Operator {
private String operator; private String operator;
public Operator(String operator) { public Operator(String operator) {

View File

@@ -69,7 +69,8 @@ public abstract class DSpaceResource<T extends RestAddressableModel> extends HAL
// TODO add support for single linked object other than for collections // TODO add support for single linked object other than for collections
Page<? extends Serializable> pageResult = (Page<? extends RestAddressableModel>) m Page<? extends Serializable> pageResult = (Page<? extends RestAddressableModel>) m
.invoke(linkRepository, null, ((BaseObjectRest) data).getId(), null, null); .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); embedded.put(name, ep);
found = true; found = true;
} }
@@ -125,7 +126,7 @@ public abstract class DSpaceResource<T extends RestAddressableModel> extends HAL
PageImpl<RestAddressableModel> page = new PageImpl(linkedRMList); PageImpl<RestAddressableModel> page = new PageImpl(linkedRMList);
wrapObject = new EmbeddedPage(linkToSubResource.getHref(), wrapObject = new EmbeddedPage(linkToSubResource.getHref(),
page.map(resourceRepository::wrapResource), page.map(resourceRepository::wrapResource),
linkedRMList); linkedRMList, name);
} else { } else {
wrapObject = null; wrapObject = null;
} }
@@ -150,7 +151,7 @@ public abstract class DSpaceResource<T extends RestAddressableModel> extends HAL
.invoke(linkRepository, null, ((BaseObjectRest) data).getId(), null, .invoke(linkRepository, null, ((BaseObjectRest) data).getId(), null,
null); null);
EmbeddedPage ep = new EmbeddedPage(linkToSubResource.getHref(), EmbeddedPage ep = new EmbeddedPage(linkToSubResource.getHref(),
pageResult, null); pageResult, null, name);
embedded.put(name, ep); embedded.put(name, ep);
} else { } else {
RestAddressableModel object = (RestAddressableModel) m RestAddressableModel object = (RestAddressableModel) m

View File

@@ -7,7 +7,9 @@
*/ */
package org.dspace.app.rest.model.hateoas; package org.dspace.app.rest.model.hateoas;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
@@ -18,25 +20,27 @@ import org.springframework.data.domain.Page;
*/ */
public class EmbeddedPage extends EmbeddedPageHeader { public class EmbeddedPage extends EmbeddedPageHeader {
private List fullList; //TODO Make map get relation name from constructor
private Map<String, List> fullMap;
public EmbeddedPage(String self, Page page, List fullList) { public EmbeddedPage(String self, Page page, List fullList, String relation) {
this(self, page, fullList, true); 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); super(self, page, totalElementsIsKnown);
this.fullList = fullList; fullMap = new HashMap<String, List>();
fullMap.put(relation, fullList);
} }
@JsonProperty(value = "_embedded") @JsonProperty(value = "_embedded")
public List getPageContent() { public Map<String, List> getPageContent() {
return page.getContent(); return fullMap;
} }
@JsonIgnore @JsonIgnore
public List getFullList() { public Map<String, List> getFullList() {
return fullList; return fullMap;
} }
} }

View File

@@ -40,7 +40,9 @@ public abstract class HALResource<T> extends Resource<T> {
public void embedResource(String relationship, HALResource resource) { public void embedResource(String relationship, HALResource resource) {
embedded.put(relationship, resource); embedded.put(relationship, resource);
} }
public void embedResource(String relationship, EmbeddedPage embeddedPage) {
embedded.put(relationship, embeddedPage);
}
public void embedResource(String relationship, Collection<? extends HALResource> resource) { public void embedResource(String relationship, Collection<? extends HALResource> resource) {
embedded.put(relationship, resource); embedded.put(relationship, resource);
} }

View File

@@ -17,6 +17,9 @@ import org.dspace.app.rest.model.SearchResultEntryRest;
import org.dspace.app.rest.model.SearchResultsRest; import org.dspace.app.rest.model.SearchResultsRest;
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource; import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
import org.dspace.app.rest.utils.Utils; 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 * This class' purpose is to create a container with a list of the SearchResultEntryResources
@@ -27,22 +30,16 @@ public class SearchResultsResource extends HALResource<SearchResultsRest> {
@JsonIgnore @JsonIgnore
private List<SearchResultEntryResource> entryResources; private List<SearchResultEntryResource> entryResources;
public SearchResultsResource(final SearchResultsRest data, final Utils utils) { public SearchResultsResource(final SearchResultsRest data, final Utils utils, Pageable pageable) {
super(data); super(data);
addEmbeds(data, utils, pageable);
addEmbeds(data, utils);
} }
private void addEmbeds(final SearchResultsRest data, final Utils utils, Pageable pageable) {
public List<SearchResultEntryResource> getEntryResources() { embedSearchResults(data, utils, pageable);
return entryResources;
}
private void addEmbeds(final SearchResultsRest data, final Utils utils) {
embedSearchResults(data, utils);
embedFacetResults(data); embedFacetResults(data);
} }
private void embedFacetResults(final SearchResultsRest data) { private void embedFacetResults(final SearchResultsRest data) {
List<SearchFacetEntryResource> facetResources = new LinkedList<>(); List<SearchFacetEntryResource> facetResources = new LinkedList<>();
for (SearchFacetEntryRest searchFacetEntryRest : CollectionUtils.emptyIfNull(data.getFacets())) { for (SearchFacetEntryRest searchFacetEntryRest : CollectionUtils.emptyIfNull(data.getFacets())) {
@@ -51,14 +48,13 @@ public class SearchResultsResource extends HALResource<SearchResultsRest> {
embedResource("facets", facetResources); embedResource("facets", facetResources);
} }
private void embedSearchResults(final SearchResultsRest data, final Utils utils, Pageable pageable) {
private void embedSearchResults(final SearchResultsRest data, final Utils utils) {
entryResources = new LinkedList<>(); entryResources = new LinkedList<>();
for (SearchResultEntryRest searchResultEntry : CollectionUtils.emptyIfNull(data.getSearchResults())) { for (SearchResultEntryRest searchResultEntry : CollectionUtils.emptyIfNull(data.getSearchResults())) {
entryResources.add(new SearchResultEntryResource(searchResultEntry, utils)); entryResources.add(new SearchResultEntryResource(searchResultEntry, utils));
} }
Page page = new PageImpl<>(entryResources, pageable, data.getTotalNumberOfResults());
embedResource("objects", entryResources); EmbeddedPage embeddedPage = new EmbeddedPage("objects", page, entryResources, "objects");
embedResource("searchResult", embeddedPage);
} }
} }

View File

@@ -819,13 +819,13 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.andExpect(jsonPath("$.type", is("discover"))) .andExpect(jsonPath("$.type", is("discover")))
//There needs to be a page object that shows the total pages and total elements as well as the //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) // size and the current page (number)
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7) PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7)
))) )))
//These search results have to be shown in the embedded.objects section as these are the items //These search results have to be shown in the embedded.objects section as these are the items
// given in the structure defined above. // given in the structure defined above.
//Seeing as everything fits onto one page, they have to all be present //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"),
SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"),
//This has to be like this because collections don't have anything else //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 //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 // 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 //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) PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7)
))) )))
//All elements have to be present in the embedded.objects section, these are the ones we made in //All elements have to be present in the embedded.objects section, these are the ones we made in
// the structure defined above // 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"),
SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"),
//Match without any parameters because collections don't have anything special to check in the //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"))) .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 //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. // 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) PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7)
))) )))
//All the elements created in the structure above have to be present in the embedded.objects section //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"),
SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"),
//Collections are specified like this because they don't have any special properties //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"))) .andExpect(jsonPath("$.type", is("discover")))
//The page object has to look like this because of the query we specified, only two elements match //The page object has to look like this because of the query we specified, only two elements match
// the query. // the query.
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 2) 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 //Only the two item elements match the query, therefore those are the only ones that can be in the
// embedded.objects section // 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"),
SearchResultMatcher.match("item", "items") SearchResultMatcher.match("item", "items")
))) )))
@@ -1148,13 +1148,13 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
//The type has to be 'discover' //The type has to be 'discover'
.andExpect(jsonPath("$.type", is("discover"))) .andExpect(jsonPath("$.type", is("discover")))
//The page element has to look like this because it contains all the elements we've just created //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) PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7)
))) )))
//The scope property has to be set to the value we entered in the parameters //The scope property has to be set to the value we entered in the parameters
.andExpect(jsonPath("$.scope", is("test"))) .andExpect(jsonPath("$.scope", is("test")))
//All the elements created in the structure above have to be present in the embedded.objects section //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"),
SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"),
//Collections are specified like this because they don't have any special properties //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"))) .andExpect(jsonPath("$.type", is("discover")))
//The page element needs to look like this and only have three totalElements because we only want //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 // 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) PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3)
))) )))
//Only the three items can be present in the embedded.objects section as that's what we specified //Only the three items can be present in the embedded.objects section as that's what we specified
// in the dsoType parameter // 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"), 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"))) .andExpect(jsonPath("$.type", is("discover")))
//The page object has to look like this and only contain three total elements because we only want //The page object has to look like this and only contain three total elements because we only want
// to get the items back // to get the items back
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3) PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 3)
))) )))
//Only the three items can be present in the embedded.objects section as that's what we specified //Only the three items can be present in the embedded.objects section as that's what we specified
// in the dsoType parameter // 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"), 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 //Here we want to match on the item name in a certain specified order because we want to check the
// sort properly // sort properly
//We check whether the items are sorted properly as we expected //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", "Public"),
SearchResultMatcher.matchOnItemName("item", "items", "Test"), SearchResultMatcher.matchOnItemName("item", "items", "Test"),
SearchResultMatcher.matchOnItemName("item", "items", "Testing") SearchResultMatcher.matchOnItemName("item", "items", "Testing")
@@ -1522,12 +1522,12 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
//Page number 1 because that's the param we entered //Page number 1 because that's the param we entered
//TotalPages 4 because size = 2 and total elements is 7 -> 4 pages //TotalPages 4 because size = 2 and total elements is 7 -> 4 pages
//We made 7 elements -> 7 total elements //We made 7 elements -> 7 total elements
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntryWithTotalPagesAndElements(1, 2, 4, 7) PageMatcher.pageEntryWithTotalPagesAndElements(1, 2, 4, 7)
))) )))
//These are the two elements that'll be shown (because page = 1, so the third and fourth element //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 // 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(),
SearchResultMatcher.match() SearchResultMatcher.match()
))) )))
@@ -1608,11 +1608,11 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
//The type has to be 'discover' //The type has to be 'discover'
.andExpect(jsonPath("$.type", is("discover"))) .andExpect(jsonPath("$.type", is("discover")))
//The page object needs to look like this //The page object needs to look like this
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntry(0, 20) PageMatcher.pageEntry(0, 20)
))) )))
//This is the only item that should be returned with the query given //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") SearchResultMatcher.matchOnItemName("item", "items", "Test")
))) )))
@@ -1685,11 +1685,11 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
//The type has to be 'discover' //The type has to be 'discover'
.andExpect(jsonPath("$.type", is("discover"))) .andExpect(jsonPath("$.type", is("discover")))
//The page object needs to look like this //The page object needs to look like this
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntry(0, 20) PageMatcher.pageEntry(0, 20)
))) )))
//These are the items that aren't set to private //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"),
SearchResultMatcher.match("community", "communities"), SearchResultMatcher.match("community", "communities"),
//Collections are specified like this because they don't have any special properties //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") SearchResultMatcher.matchOnItemName("item", "items", "Public item 2")
))) )))
//This is a private item, this shouldn't show up in the result //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")))) 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 //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) // 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' //The type has to be 'discover'
.andExpect(jsonPath("$.type", is("discover"))) .andExpect(jsonPath("$.type", is("discover")))
//The page object needs to look like this //The page object needs to look like this
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntry(0, 20) PageMatcher.pageEntry(0, 20)
))) )))
//The search results have to contain the items belonging to the scope specified //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", "Test 2"),
SearchResultMatcher.matchOnItemName("item", "items", "Public item 2") SearchResultMatcher.matchOnItemName("item", "items", "Public item 2")
))) )))
@@ -1929,17 +1929,17 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
//The type has to be 'discover' //The type has to be 'discover'
.andExpect(jsonPath("$.type", is("discover"))) .andExpect(jsonPath("$.type", is("discover")))
//The page object needs to look like this //The page object needs to look like this
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntry(0, 20) PageMatcher.pageEntry(0, 20)
))) )))
//Make sure that the search results contains the item with the correct scope //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", "Test 2")
// SearchResultMatcher.matchOnItemName("item", "items", "Public item 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 //Make sure that the search result doesn't contain the item that's set to private but does have
// the correct scope // 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") SearchResultMatcher.matchOnItemName("item", "items", "Public item 2")
)))) ))))
//These facets have to show up in the embedded.facets section as well with the given hasMore //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' //The type has to be 'discover'
.andExpect(jsonPath("$.type", is("discover"))) .andExpect(jsonPath("$.type", is("discover")))
//The page object needs to look like this //The page object needs to look like this
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntry(0, 20) PageMatcher.pageEntry(0, 20)
))) )))
//The search results has to contain the item with the query in the title and the hithighlight has //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 // 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 SearchResultMatcher
.matchOnItemNameAndHitHighlight("item", "items", "Public item 2", query, "dc.title") .matchOnItemNameAndHitHighlight("item", "items", "Public item 2", query, "dc.title")
))) )))
@@ -2081,11 +2081,11 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
//The type has to be 'discover' //The type has to be 'discover'
.andExpect(jsonPath("$.type", is("discover"))) .andExpect(jsonPath("$.type", is("discover")))
//The page object needs to look like this //The page object needs to look like this
.andExpect(jsonPath("$.page", is( .andExpect(jsonPath("$._embedded.searchResult.page", is(
PageMatcher.pageEntry(0, 20) PageMatcher.pageEntry(0, 20)
))) )))
//The search results should not contain this //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 SearchResultMatcher
.matchOnItemNameAndHitHighlight("item", "items", "Public item 2", query, "dc.title") .matchOnItemNameAndHitHighlight("item", "items", "Public item 2", query, "dc.title")
)))) ))))

View File

@@ -23,6 +23,7 @@ public class FacetEntryMatcher {
return allOf( return allOf(
hasJsonPath("$.name", is("author")), hasJsonPath("$.name", is("author")),
hasJsonPath("$.facetType", is("text")), hasJsonPath("$.facetType", is("text")),
hasJsonPath("$.facetLimit", is(10)),
hasJsonPath("$._links.self.href", containsString("api/discover/facets/author")), hasJsonPath("$._links.self.href", containsString("api/discover/facets/author")),
hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/author")) hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/author"))
); );
@@ -32,6 +33,7 @@ public class FacetEntryMatcher {
return allOf( return allOf(
hasJsonPath("$.name", is("subject")), hasJsonPath("$.name", is("subject")),
hasJsonPath("$.facetType", is("hierarchical")), hasJsonPath("$.facetType", is("hierarchical")),
hasJsonPath("$.facetLimit", is(10)),
hasJsonPath("$._links.self.href", containsString("api/discover/facets/subject")), hasJsonPath("$._links.self.href", containsString("api/discover/facets/subject")),
hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/subject")) hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/subject"))
@@ -42,6 +44,7 @@ public class FacetEntryMatcher {
return allOf( return allOf(
hasJsonPath("$.name", is("dateIssued")), hasJsonPath("$.name", is("dateIssued")),
hasJsonPath("$.facetType", is("date")), hasJsonPath("$.facetType", is("date")),
hasJsonPath("$.facetLimit", is(10)),
hasJsonPath("$._links.self.href", containsString("api/discover/facets/dateIssued")), hasJsonPath("$._links.self.href", containsString("api/discover/facets/dateIssued")),
hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/dateIssued")) hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/dateIssued"))
); );
@@ -51,6 +54,7 @@ public class FacetEntryMatcher {
return allOf( return allOf(
hasJsonPath("$.name", is("has_content_in_original_bundle")), hasJsonPath("$.name", is("has_content_in_original_bundle")),
hasJsonPath("$.facetType", is("standard")), hasJsonPath("$.facetType", is("standard")),
hasJsonPath("$.facetLimit", is(2)),
hasJsonPath("$._links.self.href", containsString("api/discover/facets/has_content_in_original_bundle")), 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")) hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/has_content_in_original_bundle"))
); );

View File

@@ -113,6 +113,7 @@
<list> <list>
<ref bean="sortTitle" /> <ref bean="sortTitle" />
<ref bean="sortDateIssued" /> <ref bean="sortDateIssued" />
<ref bean="sortDateAccessioned"/>
</list> </list>
</property> </property>
</bean> </bean>
@@ -220,6 +221,7 @@
<list> <list>
<ref bean="sortTitle" /> <ref bean="sortTitle" />
<ref bean="sortDateIssued" /> <ref bean="sortDateIssued" />
<ref bean="sortDateAccessioned" />
</list> </list>
</property> </property>
</bean> </bean>
@@ -401,6 +403,7 @@
</list> </list>
</property> </property>
<property name="type" value="date"/> <property name="type" value="date"/>
<property name="facetLimit" value="10"/>
<property name="sortOrderSidebar" value="COUNT"/> <property name="sortOrderSidebar" value="COUNT"/>
<property name="sortOrderFilterPage" value="COUNT"/> <property name="sortOrderFilterPage" value="COUNT"/>
<property name="isOpenByDefault" value="false"/> <property name="isOpenByDefault" value="false"/>
@@ -429,5 +432,8 @@
<property name="metadataField" value="dc.date.issued"/> <property name="metadataField" value="dc.date.issued"/>
<property name="type" value="date"/> <property name="type" value="date"/>
</bean> </bean>
<bean id="sortDateAccessioned" class="org.dspace.discovery.configuration.DiscoverySortFieldConfiguration">
<property name="metadataField" value="dc.date.accessioned"/>
<property name="type" value="date"/>
</bean>
</beans> </beans>