115434: Added relatedEntityType parameter to byLabel endpoint to differentiate relationships with same label and different entity types

This commit is contained in:
Alexandre Vryghem
2024-05-27 00:17:53 +02:00
parent 5a43e6bcf1
commit 8512fab392
2 changed files with 83 additions and 7 deletions

View File

@@ -29,9 +29,11 @@ import org.dspace.app.rest.model.RelationshipRest;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.EntityType;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.Relationship; import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType; import org.dspace.content.RelationshipType;
import org.dspace.content.service.EntityTypeService;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.content.service.RelationshipService; import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.RelationshipTypeService; import org.dspace.content.service.RelationshipTypeService;
@@ -60,6 +62,9 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
private static final String RIGHT = "right"; private static final String RIGHT = "right";
private static final String CONFIGURED = "configured"; private static final String CONFIGURED = "configured";
@Autowired
private EntityTypeService entityTypeService;
@Autowired @Autowired
private ItemService itemService; private ItemService itemService;
@@ -331,6 +336,7 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
* *
* @param label The label of a RelationshipType which the Relationships must have if they're to be returned * @param label The label of a RelationshipType which the Relationships must have if they're to be returned
* @param dsoId The dsoId of the object that has to be a leftItem or rightItem if this parameter is present * @param dsoId The dsoId of the object that has to be a leftItem or rightItem if this parameter is present
* @param relatedEntityType The entity type that the items who have a relationship with the given dso should have
* @param pageable The page object * @param pageable The page object
* @return A page with all the RelationshipRest objects that correspond to the constraints * @return A page with all the RelationshipRest objects that correspond to the constraints
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
@@ -338,6 +344,7 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
@SearchRestMethod(name = "byLabel") @SearchRestMethod(name = "byLabel")
public Page<RelationshipRest> findByLabel(@Parameter(value = "label", required = true) String label, public Page<RelationshipRest> findByLabel(@Parameter(value = "label", required = true) String label,
@Parameter(value = "dso", required = false) UUID dsoId, @Parameter(value = "dso", required = false) UUID dsoId,
@Parameter(value = "relatedEntityType") String relatedEntityType,
Pageable pageable) throws SQLException { Pageable pageable) throws SQLException {
Context context = obtainContext(); Context context = obtainContext();
@@ -352,14 +359,28 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
if (item == null) { if (item == null) {
throw new ResourceNotFoundException("The request DSO with id: " + dsoId + " was not found"); 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) { for (RelationshipType relationshipType : relationshipTypeList) {
boolean isLeft = false; if (relatedEntityType == null ||
if (relationshipType.getLeftwardType().equalsIgnoreCase(label)) { relationshipType.getRightType().getLabel().equals(dsoEntityType.getLabel()) &&
isLeft = true; 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 { } else {
for (RelationshipType relationshipType : relationshipTypeList) { for (RelationshipType relationshipType : relationshipTypeList) {
@@ -377,7 +398,7 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
* of potentially related items we need to know which of these other items * of potentially related items we need to know which of these other items
* are already in a specific relationship with the focus item and, * are already in a specific relationship with the focus item and,
* by exclusion which ones are not yet related. * by exclusion which ones are not yet related.
* *
* @param typeId The relationship type id to apply as a filter to the returned relationships * @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 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' * @param focusUUID The uuid of the item to be checked on the side defined by 'relationshipLabel'

View File

@@ -2323,6 +2323,61 @@ public class RelationshipRestRepositoryIT extends AbstractEntityIntegrationTest
; ;
} }
@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)
)))
;
}
@Test @Test
public void putRelationshipWithNonexistentID() throws Exception { public void putRelationshipWithNonexistentID() throws Exception {
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();