diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java index 21f43ddacd63..6be4f390daa9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java @@ -29,9 +29,11 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.DSpaceObject; +import org.dspace.content.EntityType; import org.dspace.content.Item; import org.dspace.content.Relationship; import org.dspace.content.RelationshipType; +import org.dspace.content.service.EntityTypeService; import org.dspace.content.service.ItemService; import org.dspace.content.service.RelationshipService; import org.dspace.content.service.RelationshipTypeService; @@ -60,6 +62,9 @@ public class RelationshipRestRepository extends DSpaceRestRepository findByLabel(@Parameter(value = "label", required = true) String label, @Parameter(value = "dso", required = false) UUID dsoId, + @Parameter(value = "relatedEntityType") String relatedEntityType, Pageable pageable) throws SQLException { Context context = obtainContext(); @@ -352,14 +359,28 @@ public Page findByLabel(@Parameter(value = "label", required = if (item == null) { throw new ResourceNotFoundException("The request DSO with id: " + dsoId + " was not found"); } + + EntityType dsoEntityType = itemService.getEntityType(context, item); + + if (dsoEntityType == null) { + throw new UnprocessableEntityException(String.format( + "The request DSO with id: %s doesn't have an entity type", dsoId)); + } + for (RelationshipType relationshipType : relationshipTypeList) { - boolean isLeft = false; - if (relationshipType.getLeftwardType().equalsIgnoreCase(label)) { - isLeft = true; + if (relatedEntityType == null || + relationshipType.getRightType().getLabel().equals(dsoEntityType.getLabel()) && + relationshipType.getLeftType().getLabel().equals(relatedEntityType) || + relationshipType.getRightType().getLabel().equals(relatedEntityType) && + relationshipType.getLeftType().getLabel().equals(dsoEntityType.getLabel())) { + boolean isLeft = relationshipType.getLeftwardType().equalsIgnoreCase(label); + total += + relationshipService.countByItemAndRelationshipType(context, item, relationshipType, isLeft); + relationships.addAll( + relationshipService.findByItemAndRelationshipType(context, item, relationshipType, + isLeft, pageable.getPageSize(), + Math.toIntExact(pageable.getOffset()))); } - total += relationshipService.countByItemAndRelationshipType(context, item, relationshipType, isLeft); - relationships.addAll(relationshipService.findByItemAndRelationshipType(context, item, relationshipType, - isLeft, pageable.getPageSize(), Math.toIntExact(pageable.getOffset()))); } } else { for (RelationshipType relationshipType : relationshipTypeList) { @@ -377,7 +398,7 @@ public Page findByLabel(@Parameter(value = "label", required = * of potentially related items we need to know which of these other items * are already in a specific relationship with the focus item and, * by exclusion which ones are not yet related. - * + * * @param typeId The relationship type id to apply as a filter to the returned relationships * @param label The name of the relation as defined from the side of the 'focusItem' * @param focusUUID The uuid of the item to be checked on the side defined by 'relationshipLabel' diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java index d8e53c770c70..aad26ba2c11f 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipRestRepositoryIT.java @@ -2323,6 +2323,77 @@ public void findRelationshipByLabelTest() throws Exception { ; } + @Test + public void findRelationshipByLabelWithRelatedEntityTypeTest() throws Exception { + context.turnOffAuthorisationSystem(); + RelationshipType isAuthorOfPublicationRelationshipTypePublication = relationshipTypeService + .findbyTypesAndTypeName(context, entityTypeService.findByEntityType(context, "Publication"), + entityTypeService.findByEntityType(context, "Person"), + "isAuthorOfPublication", "isPublicationOfAuthor"); + RelationshipType isAuthorOfPublicationRelationshipTypeOrgUnit = relationshipTypeService + .findbyTypesAndTypeName(context, entityTypeService.findByEntityType(context, "Publication"), + entityTypeService.findByEntityType(context, "OrgUnit"), + "isAuthorOfPublication", "isPublicationOfAuthor"); + + // We're creating a Relationship of type isAuthorOfPublication between a Publication and a Person + Relationship relationship1 = RelationshipBuilder + .createRelationshipBuilder(context, publication1, author1, isAuthorOfPublicationRelationshipTypePublication) + .build(); + + // We're creating a Relationship of type isAuthorOfPublication between a Publication and an OrgUnit + Relationship relationship2 = RelationshipBuilder + .createRelationshipBuilder(context, publication1, orgUnit1, isAuthorOfPublicationRelationshipTypeOrgUnit) + .build(); + context.restoreAuthSystemState(); + + // Perform a GET request to the searchByLabel endpoint, asking for Relationships of type isAuthorOfPublication + // With an extra parameter namely DSO which resolves to the publication used by both relationships. + // Both relationships should be returned if we don't specify the DSO's related entity type + getClient().perform(get("/api/core/relationships/search/byLabel") + .param("label", "isAuthorOfPublication") + .param("dso", publication1.getID().toString()) + .param("projection", "full")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.page", is(PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 2)))) + .andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder( + RelationshipMatcher.matchRelationship(relationship1), + RelationshipMatcher.matchRelationship(relationship2) + ))) + ; + + // Perform a GET request to the searchByLabel endpoint, asking for Relationships of type isAuthorOfPublication + // With an extra parameter namely DSO which resolves to the publication used by both relationships. + // Only the Person relationship should be returned if we specify the DSO's related entity type + getClient().perform(get("/api/core/relationships/search/byLabel") + .param("label", "isAuthorOfPublication") + .param("dso", publication1.getID().toString()) + .param("relatedEntityType", "Person") + .param("projection", "full")) + + .andExpect(status().isOk()) + .andExpect(jsonPath("$.page", is(PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 1)))) + .andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder( + RelationshipMatcher.matchRelationship(relationship1) + ))) + ; + + // Perform a GET request to the searchByLabel endpoint, asking for Relationships of type isAuthorOfPublication + // With an extra parameter namely DSO which resolves to the publication used by both relationships. + // Only the OrgUnit relationship should be returned if we specify the DSO's related entity type + getClient().perform(get("/api/core/relationships/search/byLabel") + .param("label", "isAuthorOfPublication") + .param("dso", publication1.getID().toString()) + .param("relatedEntityType", "OrgUnit") + .param("projection", "full")) + + .andExpect(status().isOk()) + .andExpect(jsonPath("$.page", is(PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 1)))) + .andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder( + RelationshipMatcher.matchRelationship(relationship2) + ))) + ; + } + @Test public void putRelationshipWithNonexistentID() throws Exception { context.turnOffAuthorisationSystem();