mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 10:04:21 +00:00
[TLC-380] Refactor browses endpoint for browse link usage
This commit is contained in:
@@ -7,12 +7,18 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.rest.repository;
|
package org.dspace.app.rest.repository;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.Parameter;
|
||||||
|
import org.dspace.app.rest.SearchRestMethod;
|
||||||
import org.dspace.app.rest.model.BrowseIndexRest;
|
import org.dspace.app.rest.model.BrowseIndexRest;
|
||||||
import org.dspace.browse.BrowseException;
|
import org.dspace.browse.BrowseException;
|
||||||
import org.dspace.browse.BrowseIndex;
|
import org.dspace.browse.BrowseIndex;
|
||||||
|
import org.dspace.browse.CrossLinks;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@@ -53,6 +59,65 @@ public class BrowseIndexRestRepository extends DSpaceRestRepository<BrowseIndexR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a browse index by a specific field
|
||||||
|
* @param field
|
||||||
|
* @return
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@SearchRestMethod(name = "byField")
|
||||||
|
public BrowseIndexRest findByField(@Parameter(value = "field", required = true) String field)
|
||||||
|
throws SQLException {
|
||||||
|
BrowseIndexRest bi = null;
|
||||||
|
BrowseIndex bix = null;
|
||||||
|
try {
|
||||||
|
CrossLinks cl = new CrossLinks();
|
||||||
|
if (cl.hasLink(field)) {
|
||||||
|
// Get the index name for this
|
||||||
|
String browseIndexName = cl.getLinkType(field);
|
||||||
|
bix = BrowseIndex.getBrowseIndex(browseIndexName);
|
||||||
|
}
|
||||||
|
} catch (BrowseException e) {
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
if (bix != null) {
|
||||||
|
bi = converter.toRest(bix, utils.obtainProjection());
|
||||||
|
}
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get paginated list of all browse index definitions for configured browse links
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* the dspace context
|
||||||
|
* @param pageable
|
||||||
|
* object embedding the requested pagination info
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@SearchRestMethod(name = "allLinked")
|
||||||
|
public Page<BrowseIndexRest> findAllLinked(Context context, Pageable pageable) {
|
||||||
|
try {
|
||||||
|
CrossLinks cl = new CrossLinks();
|
||||||
|
List<BrowseIndex> linkedIndexes = new ArrayList<>();
|
||||||
|
Map<String, String> links = cl.getLinks();
|
||||||
|
for (String field : links.keySet()) {
|
||||||
|
if (cl.hasLink(field)) {
|
||||||
|
String indexName = cl.getLinkType(field);
|
||||||
|
if (indexName != null) {
|
||||||
|
BrowseIndex bix = BrowseIndex.getBrowseIndex(indexName);
|
||||||
|
if (bix != null) {
|
||||||
|
linkedIndexes.add(bix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return converter.toRestPage(linkedIndexes, pageable, linkedIndexes.size(), utils.obtainProjection());
|
||||||
|
} catch (BrowseException e) {
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<BrowseIndexRest> getDomainClass() {
|
public Class<BrowseIndexRest> getDomainClass() {
|
||||||
return BrowseIndexRest.class;
|
return BrowseIndexRest.class;
|
||||||
|
@@ -1,101 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.app.rest.repository;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.dspace.app.rest.model.BrowseIndexRest;
|
|
||||||
import org.dspace.browse.BrowseException;
|
|
||||||
import org.dspace.browse.BrowseIndex;
|
|
||||||
import org.dspace.browse.CrossLinks;
|
|
||||||
import org.dspace.core.Context;
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the repository responsible for listing link behaviour for various browse definitions and fields.
|
|
||||||
* Note "link" here refers to rendering an HTML link from a displayed metadata value to a browse page
|
|
||||||
* not a HAL _link
|
|
||||||
*
|
|
||||||
* @author Kim Shepherd
|
|
||||||
*/
|
|
||||||
@Component(BrowseIndexRest.CATEGORY + ".browselink")
|
|
||||||
public class BrowseLinkRestRepository extends DSpaceRestRepository<BrowseIndexRest, String> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a browse definition for a given metadata field name if it is configured
|
|
||||||
* as a browse link, or null (404)
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* the dspace context
|
|
||||||
* @param metadataField
|
|
||||||
* the rest object id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@PreAuthorize("permitAll()")
|
|
||||||
public BrowseIndexRest findOne(Context context, String metadataField) {
|
|
||||||
BrowseIndexRest bi = null;
|
|
||||||
BrowseIndex bix = null;
|
|
||||||
try {
|
|
||||||
CrossLinks cl = new CrossLinks();
|
|
||||||
if (cl.hasLink(metadataField)) {
|
|
||||||
// Get the index name for this
|
|
||||||
String browseIndexName = cl.getLinkType(metadataField);
|
|
||||||
bix = BrowseIndex.getBrowseIndex(browseIndexName);
|
|
||||||
}
|
|
||||||
} catch (BrowseException e) {
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
if (bix != null) {
|
|
||||||
bi = converter.toRest(bix, utils.obtainProjection());
|
|
||||||
}
|
|
||||||
return bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get paginated list of all browse index definitions for configured browse links
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* the dspace context
|
|
||||||
* @param pageable
|
|
||||||
* object embedding the requested pagination info
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Page<BrowseIndexRest> findAll(Context context, Pageable pageable) {
|
|
||||||
try {
|
|
||||||
CrossLinks cl = new CrossLinks();
|
|
||||||
List<BrowseIndex> linkedIndexes = new ArrayList<>();
|
|
||||||
Map<String, String> links = cl.getLinks();
|
|
||||||
for (String field : links.keySet()) {
|
|
||||||
if (cl.hasLink(field)) {
|
|
||||||
String indexName = cl.getLinkType(field);
|
|
||||||
if (indexName != null) {
|
|
||||||
BrowseIndex bix = BrowseIndex.getBrowseIndex(indexName);
|
|
||||||
if (bix != null) {
|
|
||||||
linkedIndexes.add(bix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return converter.toRestPage(linkedIndexes, pageable, linkedIndexes.size(), utils.obtainProjection());
|
|
||||||
} catch (BrowseException e) {
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<BrowseIndexRest> getDomainClass() {
|
|
||||||
return BrowseIndexRest.class;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,90 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.app.rest;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
|
||||||
import static org.hamcrest.Matchers.hasSize;
|
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
||||||
|
|
||||||
import org.dspace.app.rest.matcher.BrowseIndexMatcher;
|
|
||||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
|
||||||
import org.dspace.content.authority.service.MetadataAuthorityService;
|
|
||||||
import org.dspace.services.ConfigurationService;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Integration test to test the /api/discover/browselinks endpoint
|
|
||||||
*
|
|
||||||
* @author Kim Shepherd
|
|
||||||
*/
|
|
||||||
public class BrowseLinkRestRepositoryIT extends AbstractControllerIntegrationTest {
|
|
||||||
@Autowired
|
|
||||||
ConfigurationService configurationService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
MetadataAuthorityService metadataAuthorityService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expect a single author browse definition
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void findOne() throws Exception {
|
|
||||||
//When we call the root endpoint
|
|
||||||
getClient().perform(get("/api/discover/browselinks/dc.contributor.author"))
|
|
||||||
//The status has to be 200 OK
|
|
||||||
.andExpect(status().isOk())
|
|
||||||
//We expect the content type to be "application/hal+json;charset=UTF-8"
|
|
||||||
.andExpect(content().contentType(contentType))
|
|
||||||
|
|
||||||
//The array of browse index should have a size 1
|
|
||||||
.andExpect(jsonPath("$.id", is("author")))
|
|
||||||
|
|
||||||
//Check that all (and only) the default browse indexes are present
|
|
||||||
.andExpect(jsonPath("$.metadataBrowse", is(true)))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expect a list of browse definitions that are also configured for link rendering
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void findAll() throws Exception {
|
|
||||||
//When we call the root endpoint
|
|
||||||
getClient().perform(get("/api/discover/browselinks"))
|
|
||||||
//The status has to be 200 OK
|
|
||||||
.andExpect(status().isOk())
|
|
||||||
//We expect the content type to be "application/hal+json;charset=UTF-8"
|
|
||||||
.andExpect(content().contentType(contentType))
|
|
||||||
|
|
||||||
// Expect TWO results, author and browse (see dspace-api test data local.cfg_
|
|
||||||
.andExpect(jsonPath("$.page.size", is(20)))
|
|
||||||
.andExpect(jsonPath("$.page.totalElements", is(2)))
|
|
||||||
.andExpect(jsonPath("$.page.totalPages", is(1)))
|
|
||||||
.andExpect(jsonPath("$.page.number", is(0)))
|
|
||||||
|
|
||||||
//The array of browse index should have a size 2
|
|
||||||
.andExpect(jsonPath("$._embedded.browses", hasSize(2)))
|
|
||||||
|
|
||||||
//Check that all (and only) the default browse indexes are present
|
|
||||||
.andExpect(jsonPath("$._embedded.browses", containsInAnyOrder(
|
|
||||||
BrowseIndexMatcher.contributorBrowseIndex("asc"),
|
|
||||||
BrowseIndexMatcher.subjectBrowseIndex("asc")
|
|
||||||
)))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@@ -980,7 +980,7 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
|
|||||||
/**
|
/**
|
||||||
* This test was introduced to reproduce the bug DS-4269 Pagination links must be consistent also when there is not
|
* This test was introduced to reproduce the bug DS-4269 Pagination links must be consistent also when there is not
|
||||||
* explicit pagination parameters in the request (i.e. defaults apply)
|
* explicit pagination parameters in the request (i.e. defaults apply)
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public void browsePaginationWithoutExplicitParams() throws Exception {
|
public void browsePaginationWithoutExplicitParams() throws Exception {
|
||||||
@@ -2125,4 +2125,55 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
|
|||||||
.andExpect(jsonPath("$._embedded.items[0]._embedded.owningCollection._embedded.adminGroup",
|
.andExpect(jsonPath("$._embedded.items[0]._embedded.owningCollection._embedded.adminGroup",
|
||||||
nullValue()));
|
nullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect a single author browse definition
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void findOneLinked() throws Exception {
|
||||||
|
//When we call the root endpoint
|
||||||
|
getClient().perform(get("/api/discover/browses/search/byField?field=dc.contributor.author"))
|
||||||
|
//The status has to be 200 OK
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
//We expect the content type to be "application/hal+json;charset=UTF-8"
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
|
||||||
|
//The array of browse index should have a size 1
|
||||||
|
.andExpect(jsonPath("$.id", is("author")))
|
||||||
|
|
||||||
|
//Check that all (and only) the default browse indexes are present
|
||||||
|
.andExpect(jsonPath("$.metadataBrowse", is(true)))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect a list of browse definitions that are also configured for link rendering
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void findAllLinked() throws Exception {
|
||||||
|
//When we call the root endpoint
|
||||||
|
getClient().perform(get("/api/discover/browses/search/allLinked"))
|
||||||
|
//The status has to be 200 OK
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
//We expect the content type to be "application/hal+json;charset=UTF-8"
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
|
||||||
|
// Expect TWO results, author and browse (see dspace-api test data local.cfg_
|
||||||
|
.andExpect(jsonPath("$.page.size", is(20)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(1)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(0)))
|
||||||
|
|
||||||
|
//The array of browse index should have a size 2
|
||||||
|
.andExpect(jsonPath("$._embedded.browses", hasSize(2)))
|
||||||
|
|
||||||
|
//Check that all (and only) the default browse indexes are present
|
||||||
|
.andExpect(jsonPath("$._embedded.browses", containsInAnyOrder(
|
||||||
|
BrowseIndexMatcher.contributorBrowseIndex("asc"),
|
||||||
|
BrowseIndexMatcher.subjectBrowseIndex("asc")
|
||||||
|
)))
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user