Skip to content

Commit

Permalink
75-BE/missing-handles (#314)
Browse files Browse the repository at this point in the history
* create handle without dspace object

* new controller for import handle without dspace object

* create handle for workspaceitem

* using of existing handle if it exists (#316)

* checkstyle

* fix failed test

* added whitespace after for

* review

* removed authorization for handle creation

* remove unneeded import

* checkstyle
  • Loading branch information
Paurikova2 authored and milanmajchrak committed Jun 19, 2024
1 parent 9fe1b52 commit 624378c
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,32 @@ public String getDeadSince(Context context, String handle) throws SQLException {
format(timestamptz) : null;
}

@Override
public Handle createHandle(Context context, String handleStr) throws SQLException, AuthorizeException {
// Check authorisation: Only admins may create DC types
if (!authorizeService.isAdmin(context)) {
throw new AuthorizeException(
"Only administrators may modify the handle registry");
}

String handleId;
// Do we want to generate the new handleId or use entered handleStr?
if (StringUtils.isNotBlank(handleStr)) {
// We use handleStr entered by use
handleId = handleStr;
} else {
// We generate new handleId
handleId = createId(context);
}

Handle handle = handleDAO.create(context, new Handle());
// Set handleId
handle.setHandle(handleId);
this.save(context, handle);
log.debug("Created new Handle with handle " + handleId);
return handle;
}

/**
* Strips the part identifier from the handle
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,15 @@ public void update(Context context, Handle handleObject, String newHandle,
* @throws SQLException if database error
*/
public String getDeadSince(Context context, String handle) throws SQLException;

/**
* Create handle without dspace object.
* This method is created for migration purposes.
* @param context context
* @param handle handle of Handle object
* @return created Handle
* @throws SQLException if database error
* @throws AuthorizeException if authorization error
*/
public Handle createHandle(Context context, String handle) throws SQLException, AuthorizeException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* 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 static org.dspace.app.rest.utils.ContextUtil.obtainContext;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Objects;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.HandleRest;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Context;
import org.dspace.handle.Handle;
import org.dspace.handle.service.HandleClarinService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
* Specialized controller created for Clarin-Dspace import handle without dspace object.
*
* @author Michaela Paurikova (michaela.paurikova at dataquest.sk)
*/
@RestController
@RequestMapping("/api/clarin/import")
public class ClarinHandleImportController {
@Autowired
private HandleClarinService handleClarinService;
@Autowired
private ConverterService converter;
@Autowired
private Utils utils;

/**
* Endpoint for import handle without dspace object.
* The mapping for requested endpoint, for example
* <pre>
* {@code
* https://<dspace.server.url>/api/clarin/import/handle
* }
* </pre>
* @param request request
* @return handle converted to the rest
* @throws AuthorizeException if authorization error
* @throws SQLException if database error
*/
@PreAuthorize("hasAuthority('ADMIN')")
@RequestMapping(method = RequestMethod.POST, value = "/handle")
public HandleRest importHandle(HttpServletRequest request) throws AuthorizeException, SQLException {
Context context = obtainContext(request);
if (Objects.isNull(context)) {
throw new RuntimeException("Context is null!");
}
ObjectMapper mapper = new ObjectMapper();
HandleRest handleRest = null;
try {
ServletInputStream input = request.getInputStream();
handleRest = mapper.readValue(input, HandleRest.class);
} catch (IOException e1) {
throw new UnprocessableEntityException("Error parsing request body", e1);
}

Handle handle;
try {
handle = handleClarinService.createHandle(context, handleRest.getHandle());
//set handle attributes
handle.setResourceTypeId(handleRest.getResourceTypeID());
// Save created handle
handleClarinService.save(context, handle);
} catch (SQLException e) {
throw new RuntimeException("Error while trying to create new Handle and update it", e);
}
handleRest = converter.toRest(handle, utils.obtainProjection());
context.commit();
return handleRest;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
import org.dspace.eperson.EPerson;
import org.dspace.eperson.service.EPersonService;
import org.dspace.handle.service.HandleClarinService;
import org.dspace.handle.service.HandleService;
import org.dspace.identifier.IdentifierException;
import org.dspace.identifier.service.IdentifierService;
import org.dspace.services.ConfigurationService;
import org.dspace.util.UUIDUtils;
import org.dspace.workflow.WorkflowException;
Expand Down Expand Up @@ -81,7 +84,11 @@ public class ClarinItemImportController {
@Autowired
private Utils utils;
@Autowired
private HandleClarinService handleService;
private HandleClarinService handleClarinService;
@Autowired
private HandleService handleService;
@Autowired
private IdentifierService identifierService;
@Autowired
XmlWorkflowService workflowService;
@Autowired(required = true)
Expand All @@ -101,15 +108,15 @@ public class ClarinItemImportController {
* https://<dspace.server.url>/api/clarin/import/workspaceitem
* }
* </pre>
* @param request
* @return
* @throws AuthorizeException
* @throws SQLException
* @param request request
* @return workspaceitem converted to rest
* @throws AuthorizeException if authorization error
* @throws SQLException if database error
*/
@PreAuthorize("hasAuthority('ADMIN')")
@RequestMapping(method = RequestMethod.POST, value = "/workspaceitem")
public WorkspaceItemRest importWorkspaceItem(HttpServletRequest request)
throws AuthorizeException, SQLException {
throws AuthorizeException, SQLException, IdentifierException {
Context context = obtainContext(request);
if (Objects.isNull(context)) {
throw new RuntimeException("Context is null!");
Expand Down Expand Up @@ -178,7 +185,8 @@ public WorkspaceItemRest importWorkspaceItem(HttpServletRequest request)
item.setLastModified(itemRest.getLastModified());
metadataConverter.setMetadata(context, item, itemRest.getMetadata());
if (!Objects.isNull(itemRest.getHandle())) {
item.addHandle(handleService.findByHandle(context, itemRest.getHandle()));
//create handle
identifierService.register(context, item, itemRest.getHandle());
}

// save changes
Expand Down Expand Up @@ -267,7 +275,7 @@ public ResponseEntity importWorkflowItem(HttpServletRequest request) throws SQLE
*/
@PreAuthorize("hasAuthority('ADMIN')")
@RequestMapping(method = RequestMethod.POST, value = "/item")
public ItemRest importItem(HttpServletRequest request) throws SQLException, AuthorizeException {
public ItemRest importItem(HttpServletRequest request) throws SQLException, AuthorizeException, IOException {
Context context = obtainContext(request);
if (Objects.isNull(context)) {
throw new RuntimeException("Context is null!");
Expand Down Expand Up @@ -319,10 +327,6 @@ public ItemRest importItem(HttpServletRequest request) throws SQLException, Auth
item.setDiscoverable(itemRest.getDiscoverable());
item.setLastModified(itemRest.getLastModified());
metadataConverter.setMetadata(context, item, itemRest.getMetadata());
if (!Objects.isNull(itemRest.getHandle())) {
item.addHandle(handleService.findByHandle(context, itemRest.getHandle()));
}

// store metadata values which should not be updated by the import e.g., `dc.description.provenance`,
// `dc.date.available`, etc..
// Load these metadata fields from the `clarin-dspace.cfg`
Expand All @@ -336,7 +340,7 @@ public ItemRest importItem(HttpServletRequest request) throws SQLException, Auth
}

//remove workspaceitem and create collection2item
Item itemToReturn = installItemService.installItem(context, workspaceItem);
Item itemToReturn = installItemService.installItem(context, workspaceItem, itemRest.getHandle());
//set isArchived back to false
itemToReturn.setArchived(itemRest.getInArchive());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ protected CollectionRest createAndReturn(Context context, UUID id) throws Author
throw new UnprocessableEntityException("Parent community for id: "
+ id + " not found");
}
collection = cs.create(context, parent);
collection = cs.create(context, parent, collectionRest.getHandle());
cs.update(context, collection);
metadataConverter.mergeMetadata(context, collection, collectionRest.getMetadata());
} catch (SQLException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ private Community createCommunity(Context context, Community parent) throws Auth
Community community;

try {
community = cs.create(parent, context);
community = cs.create(parent, context, communityRest.getHandle());
cs.update(context, community);
metadataConverter.mergeMetadata(context, community, communityRest.getMetadata());
} catch (SQLException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* 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.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.rest.model.HandleRest;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.handle.Handle;
import org.dspace.handle.service.HandleClarinService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.MvcResult;

/**
* Integration test to test the /api/clarin/import/handle endpoint
*
* @author Michaela Paurikova (michaela.paurikova at dataquest.sk)
*/
public class ClarinHandleImportControllerIT extends AbstractControllerIntegrationTest {
@Autowired
private HandleClarinService handleService;

@Test
public void createHandleWithoutDSpaceObjectTest() throws Exception {
ObjectMapper mapper = new ObjectMapper();
HandleRest handleRest = new HandleRest();
handleRest.setHandle("123456789/1");
handleRest.setResourceTypeID(2);
Integer handleId = null;
String adminToken = getAuthToken(admin.getEmail(), password);
MvcResult mvcResult = getClient(adminToken).perform(post("/api/clarin/import/handle")
.content(mapper.writeValueAsBytes(handleRest))
.contentType(contentType))
.andExpect(status().isOk())
.andReturn();

String content = mvcResult.getResponse().getContentAsString();
Map<String, Object> map = mapper.readValue(content, Map.class);
handleId = Integer.valueOf(String.valueOf(map.get("id")));
//find created handle
Handle handle = handleService.findByID(context, handleId);
//control
assertEquals(handle.getHandle(), "123456789/1");
assertEquals(handle.getResourceTypeId(), (Integer)2);
assertNull(handle.getUrl());
assertNull(handle.getDSpaceObject());
//clean all
context.turnOffAuthorisationSystem();
List<Handle> handles = handleService.findAll(context);
for (Handle h: handles) {
handleService.delete(context, h);
}
context.restoreAuthSystemState();
}
}

0 comments on commit 624378c

Please sign in to comment.