diff --git a/dspace-api/src/main/java/org/dspace/content/clarin/ClarinItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/clarin/ClarinItemServiceImpl.java index 936d1e136545..08d5106491c4 100644 --- a/dspace-api/src/main/java/org/dspace/content/clarin/ClarinItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/clarin/ClarinItemServiceImpl.java @@ -18,6 +18,7 @@ import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.MetadataField; import org.dspace.content.dao.clarin.ClarinItemDAO; import org.dspace.content.service.CollectionService; import org.dspace.content.service.clarin.ClarinItemService; @@ -45,6 +46,11 @@ public List findByBitstreamUUID(Context context, UUID bitstreamUUID) throw return clarinItemDAO.findByBitstreamUUID(context, bitstreamUUID); } + @Override + public List findByHandle(Context context, MetadataField metadataField, String handle) throws SQLException { + return clarinItemDAO.findByHandle(context, metadataField, handle); + } + @Override public Community getOwningCommunity(Context context, DSpaceObject dso) { if (Objects.isNull(dso)) { diff --git a/dspace-api/src/main/java/org/dspace/content/dao/clarin/ClarinItemDAO.java b/dspace-api/src/main/java/org/dspace/content/dao/clarin/ClarinItemDAO.java index 2618214585f6..ac10470a9d77 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/clarin/ClarinItemDAO.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/clarin/ClarinItemDAO.java @@ -12,8 +12,11 @@ import java.util.UUID; import org.dspace.content.Item; +import org.dspace.content.MetadataField; import org.dspace.core.Context; public interface ClarinItemDAO { List findByBitstreamUUID(Context context, UUID bitstreamUUID) throws SQLException; + + List findByHandle(Context context, MetadataField metadataField, String handle) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/clarin/ClarinItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/clarin/ClarinItemDAOImpl.java index c4ec8a674f71..5301b0463e81 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/clarin/ClarinItemDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/clarin/ClarinItemDAOImpl.java @@ -13,6 +13,7 @@ import javax.persistence.Query; import org.dspace.content.Item; +import org.dspace.content.MetadataField; import org.dspace.content.dao.clarin.ClarinItemDAO; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; @@ -29,4 +30,16 @@ public List findByBitstreamUUID(Context context, UUID bitstreamUUID) throw return list(query); } + + @Override + public List findByHandle(Context context, MetadataField metadataField, String handle) throws SQLException { + Query query = createQuery(context, "SELECT item FROM Item as item join item.metadata metadata " + + "WHERE metadata.value = :handle AND metadata.metadataField = :metadata_field"); + + query.setParameter("handle", handle); + query.setParameter("metadata_field", metadataField); + query.setHint("org.hibernate.cacheable", Boolean.TRUE); + + return list(query); + } } diff --git a/dspace-api/src/main/java/org/dspace/content/service/clarin/ClarinItemService.java b/dspace-api/src/main/java/org/dspace/content/service/clarin/ClarinItemService.java index 029b251571d3..1ea0643bc965 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/clarin/ClarinItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/clarin/ClarinItemService.java @@ -14,6 +14,7 @@ import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.MetadataField; import org.dspace.core.Context; /** @@ -33,6 +34,15 @@ public interface ClarinItemService { */ List findByBitstreamUUID(Context context, UUID bitstreamUUID) throws SQLException; + /** + * Find Item by the Handle + * @param context DSpace context object + * @param handle String of the finding item + * @return found Item or null + * @throws SQLException database error + */ + List findByHandle(Context context, MetadataField metadataField, String handle) throws SQLException; + /** * Get item/collection/community's owning community * @param context DSpace context object diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java index 9fc443046b94..e1ab6d2b2fb6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java @@ -38,6 +38,7 @@ import org.dspace.content.Bundle; import org.dspace.content.Collection; import org.dspace.content.Item; +import org.dspace.content.MetadataField; import org.dspace.content.Relationship; import org.dspace.content.RelationshipType; import org.dspace.content.WorkspaceItem; @@ -45,6 +46,7 @@ import org.dspace.content.service.CollectionService; import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; +import org.dspace.content.service.MetadataFieldService; import org.dspace.content.service.RelationshipService; import org.dspace.content.service.RelationshipTypeService; import org.dspace.content.service.WorkspaceItemService; @@ -103,6 +105,9 @@ public class ItemRestRepository extends DSpaceObjectRestRepository findByValue(@Parameter(value = "bitstreamUUID", required = return converter.toRestPage(itemList, pageable, utils.obtainProjection()); } + + @SearchRestMethod(name = "byHandle") + public Page findByHandle(@Parameter(value = "handle", required = true) String + handle, + Pageable pageable) throws SQLException { + Context context = obtainContext(); + MetadataField metadataField = metadataFieldService.findByString(context, "dc.identifier.uri", '.'); + if (Objects.isNull(metadataField)) { + throw new UnprocessableEntityException("Cannot get item by handle because the metadata field ID for " + + "`dc.identifier.uri` wasn't found."); + } + + List itemList = clarinItemService.findByHandle(context, metadataField, handle); + return converter.toRestPage(itemList, pageable, utils.obtainProjection()); + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java index e583499e181e..46d0bc062cfe 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java @@ -4767,4 +4767,40 @@ public void submitterShouldSeeLocalNoteMetadata() throws Exception { .andExpect(jsonPath("$", existDescriptionProvenanceMetadataMatcher)); } + /** + * Should find Item by the full handle identifier. + */ + @Test + public void searchByHandle() throws Exception { + context.turnOffAuthorisationSystem(); + //** GIVEN ** + 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(); + + Item publicItem1 = ItemBuilder.createItem(context, col1) + .withTitle("Public item 1") + .withIssueDate("2017-10-17") + .withAuthor("Smith, Donald").withAuthor("Doe, John") + .withSubject("ExtraEntry") + .build(); + context.restoreAuthSystemState(); + + String handlePrefix = configurationService.getProperty("handle.canonical.prefix"); + String fullHandleIdentifier = handlePrefix + publicItem1.getHandle(); + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(get("/api/core/items/search/byHandle") + .param("handle", fullHandleIdentifier)) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._embedded.items", Matchers.containsInRelativeOrder( + ItemMatcher.matchItemProperties(publicItem1) + ))); + } + }