diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RelationshipRestController.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RelationshipRestController.java index a849445bd2..d3d197863b 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RelationshipRestController.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RelationshipRestController.java @@ -8,36 +8,18 @@ package org.dspace.app.rest; import java.sql.SQLException; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.converter.RelationshipConverter; -import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.model.RelationshipRest; -import org.dspace.app.rest.model.RelationshipRestWrapper; -import org.dspace.app.rest.model.hateoas.RelationshipResourceWrapper; import org.dspace.app.rest.repository.RelationshipRestRepository; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.Utils; -import org.dspace.content.Item; -import org.dspace.content.Relationship; -import org.dspace.content.RelationshipType; -import org.dspace.content.service.ItemService; -import org.dspace.content.service.RelationshipService; -import org.dspace.content.service.RelationshipTypeService; import org.dspace.core.Context; -import org.dspace.util.UUIDUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Pageable; -import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -47,110 +29,28 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/api/core/relationships") public class RelationshipRestController { - /** - * Regular expression in the request mapping to accept a string as identifier but not the other kind of - * identifier (digits or uuid) - */ - private static final String REGEX_REQUESTMAPPING_LABEL = "/{label:^(?!^\\d+$)" + - "(?!^[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}$)[\\w+\\-]+$+}"; - /** * Regular expression in the request mapping to accept number as identifier */ private static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT = "/{id:\\d+}"; - @Autowired - private RelationshipTypeService relationshipTypeService; - @Autowired private RelationshipRestRepository relationshipRestRepository; - @Autowired - private RelationshipService relationshipService; - - @Autowired - private ItemService itemService; - - @Autowired - private RelationshipConverter relationshipConverter; - @Autowired Utils utils; - @Autowired - private HalLinkService halLinkService; - - /** - * This method will retrieve all the Relationships that have a RelationshipType which has a left or right label - * equal to the one passed along in the pathvariable. - * This is further filtered by an optional dso parameter to filter on only the relationships for the given dso - * if this is applicable - * - * @param response The response object - * @param request The request object - * @param label The label on which the Relationship's RelationshipType will be matched - * @param dsoId The ID of the dso on which we'll search for relationships if applicable - * @param pageable The page object - * @return A Resource containing all the relationships that meet the criteria - * @throws Exception If something goes wrong - */ - @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_LABEL) - public RelationshipResourceWrapper retrieveByLabel(HttpServletResponse response, - HttpServletRequest request, @PathVariable String label, - @RequestParam(name = "dso", required = false) String dsoId, - Pageable pageable) - throws Exception { - - Context context = ContextUtil.obtainContext(request); - - List relationshipTypeList = relationshipTypeService.findByLeftOrRightLabel(context, label); - List relationships = new LinkedList<>(); - if (StringUtils.isNotBlank(dsoId)) { - - UUID uuid = UUIDUtils.fromString(dsoId); - Item item = itemService.find(context, uuid); - - if (item == null) { - throw new ResourceNotFoundException("The request DSO with id: " + dsoId + " was not found"); - } - for (RelationshipType relationshipType : relationshipTypeList) { - relationships.addAll(relationshipService.findByItemAndRelationshipType(context, - item, relationshipType)); - } - } else { - for (RelationshipType relationshipType : relationshipTypeList) { - relationships.addAll(relationshipService.findByRelationshipType(context, relationshipType)); - } - } - - List relationshipRests = new LinkedList<>(); - for (Relationship relationship : relationships) { - relationshipRests.add(relationshipConverter.fromModel(relationship)); - } - - RelationshipRestWrapper relationshipRestWrapper = new RelationshipRestWrapper(); - relationshipRestWrapper.setLabel(label); - relationshipRestWrapper.setDsoId(dsoId); - relationshipRestWrapper.setRelationshipRestList(relationshipRests); - - RelationshipResourceWrapper relationshipResourceWrapper = new RelationshipResourceWrapper( - relationshipRestWrapper, utils, relationshipRests.size(), pageable); - - halLinkService.addLinks(relationshipResourceWrapper, pageable); - return relationshipResourceWrapper; - } - /** * Method to change the left item of a relationship with a given item in the body * @return The modified relationship */ @RequestMapping(method = RequestMethod.PUT, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT + "/leftItem", - consumes = {"text/uri-list"}) + consumes = {"text/uri-list"}) public RelationshipRest updateRelationshipLeft(@PathVariable Integer id, HttpServletResponse response, - HttpServletRequest request) throws SQLException { + HttpServletRequest request) throws SQLException { Context context = ContextUtil.obtainContext(request); - return relationshipRestRepository.put(context,"/api/core/relationships/", id, - utils.getStringListFromRequest(request), false); + return relationshipRestRepository.put(context, "/api/core/relationships/", id, + utils.getStringListFromRequest(request), false); } /** @@ -158,11 +58,11 @@ public class RelationshipRestController { * @return The modified relationship */ @RequestMapping(method = RequestMethod.PUT, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT + "/rightItem", - consumes = {"text/uri-list"}) + consumes = {"text/uri-list"}) public RelationshipRest updateRelationshipRight(@PathVariable Integer id, HttpServletResponse response, - HttpServletRequest request) throws SQLException { + HttpServletRequest request) throws SQLException { Context context = ContextUtil.obtainContext(request); - return relationshipRestRepository.put(context,"/api/core/relationships/", id, - utils.getStringListFromRequest(request), true); + return relationshipRestRepository.put(context, "/api/core/relationships/", id, + utils.getStringListFromRequest(request), true); } } \ No newline at end of file diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/relation/RelationshipResourceWrapperHalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/relation/RelationshipResourceWrapperHalLinkFactory.java deleted file mode 100644 index 36fb3e3f4d..0000000000 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/relation/RelationshipResourceWrapperHalLinkFactory.java +++ /dev/null @@ -1,75 +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.link.relation; - -import java.util.LinkedList; - -import org.dspace.app.rest.RelationshipRestController; -import org.dspace.app.rest.link.HalLinkFactory; -import org.dspace.app.rest.model.RelationshipRest; -import org.dspace.app.rest.model.RelationshipRestWrapper; -import org.dspace.app.rest.model.hateoas.EmbeddedPage; -import org.dspace.app.rest.model.hateoas.RelationshipResourceWrapper; -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' purpose is to add the links to the RelationshipResourceWrapper. This function and class will be called - * and used - * when the HalLinkService addLinks methods is called as it'll iterate over all the different factories and check - * whether - * these are allowed to create links for said resource or not. - */ -@Component -public class RelationshipResourceWrapperHalLinkFactory - extends HalLinkFactory { - @Override - protected void addLinks(RelationshipResourceWrapper halResource, Pageable pageable, LinkedList list) - throws Exception { - - PageImpl page = new PageImpl<>(halResource.getContent().getRelationshipRestList(), pageable, - halResource.getContent().getRelationshipRestList().size()); - - halResource.setPageHeader(new EmbeddedPage(getSelfLink(halResource.getContent(), pageable), - page, halResource.getContent().getRelationshipRestList(), - true, "relationships")); - } - - /** - * This method will construct a self link to the RelationshipRestController.retrieveByLabel method. - * This will be constructed so that the RelationshipResourceWrapper resource can contain this selflink - * and immediately point to the correct endpoint with it. - * @param content The RelationshipRestWrapper from which we'll retrieve variables to construct the link - * @param pageable The page object - * @return The String determining the link to the correct endpoint - * @throws Exception If something goes wrong - */ - public String getSelfLink(RelationshipRestWrapper content, Pageable pageable) throws Exception { - if (content != null) { - UriComponentsBuilder uriBuilderSelfLink = uriBuilder(getMethodOn() - .retrieveByLabel(null, null, - content.getLabel(), - content.getDsoId(), pageable)); - return uriBuilderSelfLink.build().toString(); - } - return null; - } - - @Override - protected Class getControllerClass() { - return RelationshipRestController.class; - } - - @Override - protected Class getResourceClass() { - return RelationshipResourceWrapper.class; - } -} diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/RelationshipRestWrapper.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/RelationshipRestWrapper.java deleted file mode 100644 index 52b87a8fbc..0000000000 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/RelationshipRestWrapper.java +++ /dev/null @@ -1,72 +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.model; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.dspace.app.rest.RelationshipRestController; - -/** - * This is the RestWrapper object for the RelationshipRestResource class. This will contain all the data that is - * used in that resource and more specifically, the label, dsoid and list of RelationshipRest objects - * The other methods are generic getters and setters - * This will be updated in https://jira.duraspace.org/browse/DS-4084 - */ -public class RelationshipRestWrapper implements RestAddressableModel { - public static final String NAME = "relationship"; - public static final String CATEGORY = RestAddressableModel.CORE; - - @JsonIgnore - private List relationshipRestList; - - private String label; - private String dsoId; - - - - public List getRelationshipRestList() { - return relationshipRestList; - } - - public void setRelationshipRestList(List relationshipRestList) { - this.relationshipRestList = relationshipRestList; - } - - @Override - public String getCategory() { - return CATEGORY; - } - - public Class getController() { - return RelationshipRestController.class; - } - - @Override - @JsonProperty(access = JsonProperty.Access.READ_ONLY) - public String getType() { - return NAME; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public String getDsoId() { - return dsoId; - } - - public void setDsoId(String dsoId) { - this.dsoId = dsoId; - } -} diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/RelationshipResourceWrapper.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/RelationshipResourceWrapper.java deleted file mode 100644 index 0594eeb52c..0000000000 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/RelationshipResourceWrapper.java +++ /dev/null @@ -1,51 +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.model.hateoas; - -import java.util.LinkedList; -import java.util.List; - -import org.dspace.app.rest.model.RelationshipRest; -import org.dspace.app.rest.model.RelationshipRestWrapper; -import org.dspace.app.rest.utils.Utils; -import org.springframework.data.domain.Pageable; - -/** - * This is the RelationshipResourceWrapper class which will take the RelationshipRestWrapper's data and transform - * this into a resource with the data, embeds and links. - */ -public class RelationshipResourceWrapper extends HALResource { - - /** - * The constructor for the RelationshipResourceWrapper - * This will call the HALResource constructor and additionally add embeds to the resource - * @param content The RelationshipRestWrapper object that contains the data - * @param utils The Util object - * @param totalElements The total amount of elements to be included in the list - * @param pageable The pageable object - */ - public RelationshipResourceWrapper(RelationshipRestWrapper content, Utils utils, Integer totalElements, - Pageable pageable) { - super(content); - addEmbeds(content, utils, pageable); - } - - private void addEmbeds(RelationshipRestWrapper content, Utils utils, - Pageable pageable) { - List list = new LinkedList<>(); - for (RelationshipRest relationshipRest : content.getRelationshipRestList()) { - list.add(new RelationshipResource(relationshipRest, utils)); - } - int begin = pageable.getOffset(); - int end = (pageable.getOffset() + pageable.getPageSize()) > list.size() ? list.size() : - pageable.getOffset() + pageable.getPageSize(); - list = list.subList(begin, end); - embedResource("relationships", list); - } - -} diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java index 212b458712..fa0cb5a34a 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java @@ -8,10 +8,14 @@ package org.dspace.app.rest.repository; import java.sql.SQLException; +import java.util.LinkedList; import java.util.List; +import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; +import org.dspace.app.rest.Parameter; +import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.converter.RelationshipConverter; import org.dspace.app.rest.converter.RelationshipTypeConverter; import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException; @@ -47,23 +51,24 @@ public class RelationshipRestRepository extends DSpaceRestRepository findByLabel(@Parameter(value = "label", required = true) String label, + @Parameter(value = "dso", required = false) UUID dsoId, + Pageable pageable) throws SQLException { + + Context context = obtainContext(); + + List relationshipTypeList = relationshipTypeService.findByLeftOrRightLabel(context, label); + List relationships = new LinkedList<>(); + if (dsoId != null) { + + Item item = itemService.find(context, dsoId); + + if (item == null) { + throw new ResourceNotFoundException("The request DSO with id: " + dsoId + " was not found"); + } + for (RelationshipType relationshipType : relationshipTypeList) { + relationships.addAll(relationshipService.findByItemAndRelationshipType(context, + item, relationshipType)); + } + } else { + for (RelationshipType relationshipType : relationshipTypeList) { + relationships.addAll(relationshipService.findByRelationshipType(context, relationshipType)); + } + } + + Page page = utils.getPage(relationships, pageable).map(relationshipConverter); + return page; + + } } \ No newline at end of file diff --git a/dspace-spring-rest/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java b/dspace-spring-rest/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java index c5cae09ba7..c2c7de5dc0 100644 --- a/dspace-spring-rest/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java +++ b/dspace-spring-rest/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java @@ -9,6 +9,7 @@ package org.dspace.app.rest; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -2161,6 +2162,114 @@ public class RelationshipRestRepositoryIT extends AbstractEntityIntegrationTest } + @Test + public void findRelationshipByLabelTest() throws Exception { + + context.turnOffAuthorisationSystem(); + + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2").build(); + Collection col3 = CollectionBuilder.createCollection(context, child1).withName("OrgUnits").build(); + + Item auhor1 = ItemBuilder.createItem(context, col1) + .withTitle("Author1") + .withIssueDate("2017-10-17") + .withAuthor("Smith, Donald") + .withRelationshipType("Person") + .build(); + + Item author2 = ItemBuilder.createItem(context, col2) + .withTitle("Author2") + .withIssueDate("2016-02-13") + .withAuthor("Smith, Maria") + .withRelationshipType("Person") + .build(); + + Item author3 = ItemBuilder.createItem(context, col2) + .withTitle("Author3") + .withIssueDate("2016-02-13") + .withAuthor("Maybe, Maybe") + .withRelationshipType("Person") + .build(); + + Item orgUnit1 = ItemBuilder.createItem(context, col3) + .withTitle("OrgUnit1") + .withAuthor("Testy, TEst") + .withIssueDate("2015-01-01") + .withRelationshipType("OrgUnit") + .build(); + + Item project1 = ItemBuilder.createItem(context, col3) + .withTitle("Project1") + .withAuthor("Testy, TEst") + .withIssueDate("2015-01-01") + .withRelationshipType("Project") + .build(); + + Item publication = ItemBuilder.createItem(context, col3) + .withTitle("Publication1") + .withAuthor("Testy, TEst") + .withIssueDate("2015-01-01") + .withRelationshipType("Publication") + .build(); + + + RelationshipType isOrgUnitOfPersonRelationshipType = relationshipTypeService + .findbyTypesAndLabels(context, entityTypeService.findByEntityType(context, "Person"), + entityTypeService.findByEntityType(context, "OrgUnit"), + "isOrgUnitOfPerson", "isPersonOfOrgUnit"); + RelationshipType isOrgUnitOfProjectRelationshipType = relationshipTypeService + .findbyTypesAndLabels(context, entityTypeService.findByEntityType(context, "Project"), + entityTypeService.findByEntityType(context, "OrgUnit"), + "isOrgUnitOfProject", "isProjectOfOrgUnit"); + RelationshipType isAuthorOfPublicationRelationshipType = relationshipTypeService + .findbyTypesAndLabels(context, entityTypeService.findByEntityType(context, "Publication"), + entityTypeService.findByEntityType(context, "Person"), + "isAuthorOfPublication", "isPublicationOfAuthor"); + + Relationship relationship1 = RelationshipBuilder + .createRelationshipBuilder(context, auhor1, orgUnit1, isOrgUnitOfPersonRelationshipType).build(); + + Relationship relationshipAuthorExtra = RelationshipBuilder + .createRelationshipBuilder(context, author2, orgUnit1, isOrgUnitOfPersonRelationshipType).build(); + + Relationship relationship2 = RelationshipBuilder + .createRelationshipBuilder(context, project1, orgUnit1, isOrgUnitOfProjectRelationshipType).build(); + + Relationship relationship3 = RelationshipBuilder + .createRelationshipBuilder(context, publication, auhor1, isAuthorOfPublicationRelationshipType).build(); + + getClient().perform(get("/api/core/relationships/search/byLabel") + .param("label", "isOrgUnitOfPerson") + .param("dso", auhor1.getID().toString())) + + .andExpect(status().isOk()) + .andExpect(jsonPath("$.page", + is(PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 1)))) + .andExpect(jsonPath("$._embedded.relationships", hasItem( + RelationshipMatcher.matchRelationship(relationship1) + ))) + ; + + getClient().perform(get("/api/core/relationships/search/byLabel") + .param("label", "isOrgUnitOfPerson")) + + .andExpect(status().isOk()) + .andExpect(jsonPath("$.page", + is(PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 2)))) + .andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder( + RelationshipMatcher.matchRelationship(relationship1), + RelationshipMatcher.matchRelationship(relationshipAuthorExtra) + ))) + ; + } + @Test public void putRelationshipWithNonexistentID() throws Exception { context.turnOffAuthorisationSystem(); diff --git a/dspace-spring-rest/src/test/java/org/dspace/app/rest/RelationshipTypeRestControllerIT.java b/dspace-spring-rest/src/test/java/org/dspace/app/rest/RelationshipTypeRestControllerIT.java index 4f2c307ac8..8b91623858 100644 --- a/dspace-spring-rest/src/test/java/org/dspace/app/rest/RelationshipTypeRestControllerIT.java +++ b/dspace-spring-rest/src/test/java/org/dspace/app/rest/RelationshipTypeRestControllerIT.java @@ -184,7 +184,7 @@ public class RelationshipTypeRestControllerIT extends AbstractEntityIntegrationT .createRelationshipBuilder(context, publication2, author3, isAuthorOfPublicationRelationshipType).build(); context.restoreAuthSystemState(); - getClient().perform(get("/api/core/relationships/isAuthorOfPublication")) + getClient().perform(get("/api/core/relationships/search/byLabel?label=isAuthorOfPublication")) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder( RelationshipMatcher.matchRelationship(relationship1), @@ -193,14 +193,16 @@ public class RelationshipTypeRestControllerIT extends AbstractEntityIntegrationT RelationshipMatcher.matchRelationship(relationship4) ))); - getClient().perform(get("/api/core/relationships/isAuthorOfPublication?dso=" + publication.getID())) + getClient().perform(get("/api/core/relationships/search/byLabel?label=isAuthorOfPublication&dso=" + + publication.getID())) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder( RelationshipMatcher.matchRelationship(relationship1), RelationshipMatcher.matchRelationship(relationship2) ))); - getClient().perform(get("/api/core/relationships/isAuthorOfPublication?dso=" + publication2.getID())) + getClient().perform(get("/api/core/relationships/search/byLabel?label=isAuthorOfPublication&dso=" + + publication2.getID())) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder( RelationshipMatcher.matchRelationship(relationship3),