mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
65257: create and read for collection template items
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 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 java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.model.CollectionRest;
|
||||
import org.dspace.app.rest.model.ItemRest;
|
||||
import org.dspace.app.rest.model.hateoas.ItemResource;
|
||||
import org.dspace.app.rest.repository.CollectionRestRepository;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.rest.webmvc.ControllerUtils;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
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.RestController;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/" + CollectionRest.CATEGORY + "/" + CollectionRest.PLURAL_NAME)
|
||||
public class CollectionRestController {
|
||||
|
||||
/**
|
||||
* Regular expression in the request mapping to accept UUID as identifier
|
||||
*/
|
||||
private static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID =
|
||||
"{uuid:[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}}";
|
||||
|
||||
@Autowired
|
||||
protected Utils utils;
|
||||
|
||||
@Autowired
|
||||
private CollectionRestRepository collectionRestRepository;
|
||||
|
||||
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||
@RequestMapping(method = RequestMethod.POST,
|
||||
value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/itemtemplate")
|
||||
public ResponseEntity<ResourceSupport> createTemplateItem(HttpServletRequest request, @PathVariable UUID uuid)
|
||||
throws SQLException, AuthorizeException {
|
||||
|
||||
Context context = ContextUtil.obtainContext(request);
|
||||
ItemRest templateItem = collectionRestRepository.createTemplateItem(context, uuid);
|
||||
|
||||
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null,
|
||||
new ItemResource(templateItem, utils));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||
@RequestMapping(method = RequestMethod.GET,
|
||||
value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/itemtemplate")
|
||||
public ItemResource getTemplateItem(HttpServletRequest request, @PathVariable UUID uuid)
|
||||
throws SQLException {
|
||||
|
||||
Context context = ContextUtil.obtainContext(request);
|
||||
ItemRest templateItem = collectionRestRepository.getTemplateItem(context, uuid);
|
||||
|
||||
return new ItemResource(templateItem, utils);
|
||||
}
|
||||
}
|
@@ -17,11 +17,11 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.Parameter;
|
||||
import org.dspace.app.rest.SearchRestMethod;
|
||||
import org.dspace.app.rest.converter.BitstreamConverter;
|
||||
import org.dspace.app.rest.converter.CollectionConverter;
|
||||
import org.dspace.app.rest.converter.ItemConverter;
|
||||
import org.dspace.app.rest.converter.MetadataConverter;
|
||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
@@ -29,6 +29,7 @@ import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.CollectionRest;
|
||||
import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.model.ItemRest;
|
||||
import org.dspace.app.rest.model.hateoas.CollectionResource;
|
||||
import org.dspace.app.rest.model.patch.Patch;
|
||||
import org.dspace.app.rest.repository.patch.DSpaceObjectPatch;
|
||||
@@ -38,8 +39,10 @@ import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -60,9 +63,6 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
@Component(CollectionRest.CATEGORY + "." + CollectionRest.NAME)
|
||||
public class CollectionRestRepository extends DSpaceObjectRestRepository<Collection, CollectionRest> {
|
||||
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager
|
||||
.getLogger(CollectionRestRepository.class);
|
||||
|
||||
@Autowired
|
||||
CommunityService communityService;
|
||||
|
||||
@@ -84,6 +84,16 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
|
||||
@Autowired
|
||||
private BitstreamService bitstreamService;
|
||||
|
||||
@Autowired
|
||||
private ItemConverter itemConverter;
|
||||
|
||||
@Autowired
|
||||
private ItemService itemService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper mapper;
|
||||
|
||||
|
||||
public CollectionRestRepository(CollectionService dsoService,
|
||||
CollectionConverter dsoConverter) {
|
||||
super(dsoService, dsoConverter, new DSpaceObjectPatch<CollectionRest>() {});
|
||||
@@ -249,17 +259,8 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
|
||||
@Override
|
||||
@PreAuthorize("hasPermission(#id, 'COLLECTION', 'DELETE')")
|
||||
protected void delete(Context context, UUID id) throws AuthorizeException {
|
||||
Collection collection = null;
|
||||
try {
|
||||
collection = cs.find(context, id);
|
||||
if (collection == null) {
|
||||
throw new ResourceNotFoundException(
|
||||
CollectionRest.CATEGORY + "." + CollectionRest.NAME + " with id: " + id + " not found");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Unable to find Collection with id = " + id, e);
|
||||
}
|
||||
try {
|
||||
Collection collection = getCollection(context, id);
|
||||
cs.delete(context, collection);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Unable to delete Collection with id = " + id, e);
|
||||
@@ -280,15 +281,71 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
|
||||
* @throws SQLException
|
||||
*/
|
||||
public BitstreamRest setLogo(Context context, Collection collection, MultipartFile uploadfile)
|
||||
throws IOException, AuthorizeException, SQLException {
|
||||
throws IOException, AuthorizeException, SQLException {
|
||||
|
||||
if (collection.getLogo() != null) {
|
||||
throw new UnprocessableEntityException(
|
||||
"The collection with the given uuid already has a logo: " + collection.getID());
|
||||
"The collection with the given uuid already has a logo: " + collection.getID());
|
||||
}
|
||||
Bitstream bitstream = cs.setLogo(context, collection, uploadfile.getInputStream());
|
||||
cs.update(context, collection);
|
||||
bitstreamService.update(context, bitstream);
|
||||
return bitstreamConverter.fromModel(context.reloadEntity(bitstream));
|
||||
}
|
||||
|
||||
public ItemRest createTemplateItem(Context context, UUID uuid) throws SQLException, AuthorizeException {
|
||||
Collection collection = getCollection(context, uuid);
|
||||
|
||||
if (collection.getTemplateItem() != null) {
|
||||
throw new UnprocessableEntityException("Collection with ID " + uuid + " already contains a template item");
|
||||
}
|
||||
|
||||
HttpServletRequest req = getRequestService().getCurrentRequest().getHttpServletRequest();
|
||||
ItemRest inputItemRest;
|
||||
try {
|
||||
ServletInputStream input = req.getInputStream();
|
||||
inputItemRest = mapper.readValue(input, ItemRest.class);
|
||||
} catch (IOException e1) {
|
||||
throw new UnprocessableEntityException("Error parsing request body", e1);
|
||||
}
|
||||
|
||||
if (inputItemRest.getInArchive() || inputItemRest.getDiscoverable() || inputItemRest.getWithdrawn()) {
|
||||
throw new UnprocessableEntityException(
|
||||
"The template item should not be archived, discoverable or withdrawn");
|
||||
}
|
||||
|
||||
cs.createTemplateItem(context, collection);
|
||||
Item templateItem = collection.getTemplateItem();
|
||||
metadataConverter.setMetadata(context, templateItem, inputItemRest.getMetadata());
|
||||
templateItem.setDiscoverable(false);
|
||||
|
||||
cs.update(context, collection);
|
||||
itemService.update(context, templateItem);
|
||||
context.commit();
|
||||
|
||||
return itemConverter.fromModel(templateItem);
|
||||
}
|
||||
|
||||
public ItemRest getTemplateItem(Context context, UUID uuid) throws SQLException {
|
||||
Collection collection = getCollection(context, uuid);
|
||||
|
||||
Item item = collection.getTemplateItem();
|
||||
if (item == null) {
|
||||
throw new ResourceNotFoundException(
|
||||
"TemplateItem from " + CollectionRest.CATEGORY + "." + CollectionRest.NAME + " with id: "
|
||||
+ uuid + " not found");
|
||||
}
|
||||
|
||||
return itemConverter.fromModel(item);
|
||||
}
|
||||
|
||||
private Collection getCollection(Context context, UUID uuid) throws SQLException {
|
||||
Collection collection = null;
|
||||
collection = cs.find(context, uuid);
|
||||
if (collection == null) {
|
||||
throw new ResourceNotFoundException(
|
||||
CollectionRest.CATEGORY + "." + CollectionRest.NAME + " with id: " + uuid + " not found");
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* 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 com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.matcher.MetadataMatcher;
|
||||
import org.dspace.app.rest.model.ItemRest;
|
||||
import org.dspace.app.rest.model.MetadataRest;
|
||||
import org.dspace.app.rest.model.MetadataValueRest;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.content.Collection;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
public class CollectionRestControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
ObjectMapper mapper;
|
||||
private String adminAuthToken;
|
||||
private Collection childCollection;
|
||||
ItemRest testTemplateItem;
|
||||
|
||||
@Before
|
||||
public void createStructure() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
childCollection = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1").build();
|
||||
adminAuthToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
mapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
private void setupTestTemplate() {
|
||||
testTemplateItem = new ItemRest();
|
||||
testTemplateItem.setInArchive(false);
|
||||
testTemplateItem.setDiscoverable(false);
|
||||
testTemplateItem.setWithdrawn(false);
|
||||
|
||||
testTemplateItem.setMetadata(new MetadataRest()
|
||||
.put("dc.description", new MetadataValueRest("dc description content"))
|
||||
.put("dc.description.abstract", new MetadataValueRest("dc description abstract content")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTemplateItemNotLoggedIn() throws Exception {
|
||||
setupTestTemplate();
|
||||
|
||||
getClient().perform(post(
|
||||
getTemplateItemUrlTemplate(childCollection.getID().toString()))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTemplateItem() throws Exception {
|
||||
setupTestTemplate();
|
||||
|
||||
MvcResult mvcResult = getClient(adminAuthToken).perform(post(
|
||||
getTemplateItemUrlTemplate(childCollection.getID().toString()))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn();
|
||||
|
||||
String content = mvcResult.getResponse().getContentAsString();
|
||||
Map<String,Object> map = mapper.readValue(content, Map.class);
|
||||
String itemUuidString = String.valueOf(map.get("uuid"));
|
||||
|
||||
getClient(adminAuthToken).perform(get(getTemplateItemUrlTemplate(childCollection.getID().toString())))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.id", is(itemUuidString)),
|
||||
hasJsonPath("$.uuid", is(itemUuidString)),
|
||||
hasJsonPath("$.type", is("item")),
|
||||
hasJsonPath("$.inArchive", is(false)),
|
||||
hasJsonPath("$.discoverable", is(false)),
|
||||
hasJsonPath("$.withdrawn", is(false)),
|
||||
hasJsonPath("$.metadata", Matchers.allOf(
|
||||
MetadataMatcher.matchMetadata("dc.description",
|
||||
"dc description content"),
|
||||
MetadataMatcher.matchMetadata("dc.description.abstract",
|
||||
"dc description abstract content")
|
||||
)))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIllegal1TemplateItem() throws Exception {
|
||||
setupTestTemplate();
|
||||
testTemplateItem.setInArchive(true);
|
||||
|
||||
getClient(adminAuthToken).perform(post(
|
||||
getTemplateItemUrlTemplate(childCollection.getID().toString()))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isUnprocessableEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIllegal2TemplateItem() throws Exception {
|
||||
setupTestTemplate();
|
||||
testTemplateItem.setDiscoverable(true);
|
||||
|
||||
getClient(adminAuthToken).perform(post(
|
||||
getTemplateItemUrlTemplate(childCollection.getID().toString()))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isUnprocessableEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIllegal3TemplateItem() throws Exception {
|
||||
setupTestTemplate();
|
||||
testTemplateItem.setWithdrawn(true);
|
||||
|
||||
getClient(adminAuthToken).perform(post(
|
||||
getTemplateItemUrlTemplate(childCollection.getID().toString()))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isUnprocessableEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTemplateItemNoRights() throws Exception {
|
||||
setupTestTemplate();
|
||||
|
||||
String userToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(userToken).perform(post(
|
||||
getTemplateItemUrlTemplate(childCollection.getID().toString()))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDuplicateTemplateItem() throws Exception {
|
||||
setupTestTemplate();
|
||||
|
||||
getClient(adminAuthToken).perform(post(
|
||||
getTemplateItemUrlTemplate(childCollection.getID().toString()))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
getClient(adminAuthToken).perform(post(
|
||||
getTemplateItemUrlTemplate(childCollection.getID().toString()))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isUnprocessableEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTemplateItemForNonexisting() throws Exception {
|
||||
setupTestTemplate();
|
||||
|
||||
getClient(adminAuthToken).perform(post(
|
||||
getTemplateItemUrlTemplate("16a4b65b-3b3f-4ef5-8058-ef6f5a653ef9"))
|
||||
.content(mapper.writeValueAsBytes(testTemplateItem)).contentType(contentType))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
private String getTemplateItemUrlTemplate(String uuid) {
|
||||
return "/api/core/collections/" + uuid + "/itemtemplate";
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user