mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Merge pull request #1750 from 4Science/DS-3593
DS-3593 allow aggregation of endpoints by category / Include UUID in serialization
This commit is contained in:
@@ -49,7 +49,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
*
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/core/{model}")
|
||||
@RequestMapping("/api/{apiCategory}/{model}")
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class RestResourceController implements InitializingBean {
|
||||
@Autowired
|
||||
@@ -65,8 +65,9 @@ public class RestResourceController implements InitializingBean {
|
||||
// this doesn't work as we don't have an active http request
|
||||
// see https://github.com/spring-projects/spring-hateoas/issues/408
|
||||
// Link l = linkTo(this.getClass(), r).withRel(r);
|
||||
String plural = English.plural(r);
|
||||
Link l = new Link("/api/core/" + plural, plural);
|
||||
String[] split = r.split("\\.", 2);
|
||||
String plural = English.plural(split[1]);
|
||||
Link l = new Link("/api/" + split[0] + "/" + plural, plural);
|
||||
links.add(l);
|
||||
System.out.println(l.getRel() + " " + l.getHref());
|
||||
}
|
||||
@@ -75,44 +76,44 @@ public class RestResourceController implements InitializingBean {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{id:\\d+}")
|
||||
@SuppressWarnings("unchecked")
|
||||
DSpaceResource<RestModel> findOne(@PathVariable String model, @PathVariable Integer id, @RequestParam(required=false) String projection) {
|
||||
return findOneInternal(model, id, projection);
|
||||
DSpaceResource<RestModel> findOne(@PathVariable String apiCategory, @PathVariable String model, @PathVariable Integer id, @RequestParam(required=false) String projection) {
|
||||
return findOneInternal(apiCategory, model, id, projection);
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{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}}")
|
||||
@SuppressWarnings("unchecked")
|
||||
DSpaceResource<RestModel> findOne(@PathVariable String model, @PathVariable UUID uuid, @RequestParam(required=false) String projection) {
|
||||
return findOneInternal(model, uuid, projection);
|
||||
DSpaceResource<RestModel> findOne(@PathVariable String apiCategory, @PathVariable String model, @PathVariable UUID uuid, @RequestParam(required=false) String projection) {
|
||||
return findOneInternal(apiCategory, model, uuid, projection);
|
||||
}
|
||||
|
||||
private <ID extends Serializable> DSpaceResource<RestModel> findOneInternal(String model, ID id, String projection) {
|
||||
DSpaceRestRepository<RestModel, ID> repository = utils.getResourceRepository(model);
|
||||
private <ID extends Serializable> DSpaceResource<RestModel> findOneInternal(String apiCategory, String model, ID id, String projection) {
|
||||
DSpaceRestRepository<RestModel, ID> repository = utils.getResourceRepository(apiCategory, model);
|
||||
RestModel modelObject = null;
|
||||
try {
|
||||
modelObject = repository.findOne(id);
|
||||
} catch (ClassCastException e) {
|
||||
}
|
||||
if (modelObject == null) {
|
||||
throw new ResourceNotFoundException(model + " with id: " + id + " not found");
|
||||
throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found");
|
||||
}
|
||||
DSpaceResource result = repository.wrapResource(modelObject);
|
||||
return result;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{id:\\d+}/{rel}")
|
||||
ResourceSupport findRel(@PathVariable String model, @PathVariable Integer id, @PathVariable String rel, @RequestParam(required=false) String projection) {
|
||||
return findRelInternal(model, id, rel, projection);
|
||||
ResourceSupport findRel(@PathVariable String apiCategory, @PathVariable String model, @PathVariable Integer id, @PathVariable String rel, @RequestParam(required=false) String projection) {
|
||||
return findRelInternal(apiCategory, model, id, rel, projection);
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{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}}/{rel}")
|
||||
ResourceSupport findRel(@PathVariable String model, @PathVariable UUID uuid, @PathVariable String rel, @RequestParam(required=false) String projection) {
|
||||
return findRelInternal(model, uuid, rel, projection);
|
||||
ResourceSupport findRel(@PathVariable String apiCategory, @PathVariable String model, @PathVariable UUID uuid, @PathVariable String rel, @RequestParam(required=false) String projection) {
|
||||
return findRelInternal(apiCategory, model, uuid, rel, projection);
|
||||
}
|
||||
|
||||
private <ID extends Serializable> ResourceSupport findRelInternal(String model, ID uuid, String rel, String projection) {
|
||||
private <ID extends Serializable> ResourceSupport findRelInternal(String apiCategory, String model, ID uuid, String rel, String projection) {
|
||||
// FIXME this is a very bad implementation as it leads most of times to
|
||||
// more round-trip on the database and retrieval of unneeded infromation
|
||||
DSpaceRestRepository<RestModel, ID> repository = utils.getResourceRepository(model);
|
||||
DSpaceRestRepository<RestModel, ID> repository = utils.getResourceRepository(apiCategory, model);
|
||||
RestModel modelObject = repository.findOne(uuid);
|
||||
DSpaceResource result = repository.wrapResource(modelObject, rel);
|
||||
if (result.getLink(rel) == null) {
|
||||
@@ -126,15 +127,14 @@ public class RestResourceController implements InitializingBean {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@SuppressWarnings("unchecked")
|
||||
<T extends RestModel> PagedResources<DSpaceResource<T>> findAll(@PathVariable String model, Pageable page, PagedResourcesAssembler assembler, @RequestParam(required=false) String projection) {
|
||||
DSpaceRestRepository<T, ?> repository = utils.getResourceRepository(model);
|
||||
<T extends RestModel> PagedResources<DSpaceResource<T>> findAll(@PathVariable String apiCategory, @PathVariable String model, Pageable page, PagedResourcesAssembler assembler, @RequestParam(required=false) String projection) {
|
||||
DSpaceRestRepository<T, ?> repository = utils.getResourceRepository(apiCategory, model);
|
||||
// Link link = entityLinks.linkFor(getResourceClass(model), model, page).withSelfRel();
|
||||
Link link = linkTo(this.getClass(), model).withSelfRel();
|
||||
Link link = linkTo(this.getClass(), apiCategory, model).withSelfRel();
|
||||
|
||||
Page<DSpaceResource<T>> resources;
|
||||
try {
|
||||
resources = repository.findAll(page).map(repository::wrapResource);
|
||||
// resources.forEach(r -> {
|
||||
// Link linkToSingleResource = Utils.linkToSingleResource(r, Link.REL_SELF);
|
||||
// r.add(linkToSingleResource);
|
||||
// });
|
||||
|
@@ -18,9 +18,11 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
*/
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "This endpoint is not found in the system")
|
||||
public class RepositoryNotFoundException extends RuntimeException {
|
||||
String apiCategory;
|
||||
String model;
|
||||
|
||||
public RepositoryNotFoundException(String model) {
|
||||
public RepositoryNotFoundException(String apiCategory, String model) {
|
||||
this.apiCategory = apiCategory;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
|
@@ -21,7 +21,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
*/
|
||||
public class BitstreamFormatRest extends BaseObjectRest<Integer> {
|
||||
public static final String NAME = "bitstreamformat";
|
||||
|
||||
|
||||
public static final String CATEGORY = RestModel.CORE;
|
||||
|
||||
private String shortDescription;
|
||||
|
||||
private String description;
|
||||
@@ -82,6 +84,12 @@ public class BitstreamFormatRest extends BaseObjectRest<Integer> {
|
||||
this.extensions = extensions;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
|
@@ -17,6 +17,7 @@ import com.fasterxml.jackson.annotation.JsonProperty.Access;
|
||||
*/
|
||||
public class BitstreamRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "bitstream";
|
||||
public static final String CATEGORY = RestModel.CORE;
|
||||
private String bundleName;
|
||||
|
||||
// avoid to serialize this object inline as we want a full resource embedded
|
||||
@@ -68,6 +69,11 @@ public class BitstreamRest extends DSpaceObjectRest {
|
||||
this.sequenceId = sequenceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
|
@@ -15,7 +15,13 @@ package org.dspace.app.rest.model;
|
||||
*/
|
||||
public class CollectionRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "collection";
|
||||
public static final String CATEGORY = RestModel.CORE;
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
|
@@ -15,7 +15,13 @@ package org.dspace.app.rest.model;
|
||||
*/
|
||||
public class CommunityRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "community";
|
||||
|
||||
public static final String CATEGORY = RestModel.CORE;
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
|
@@ -11,8 +11,6 @@ import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* Base REST representation for all the DSpaceObjects
|
||||
*
|
||||
@@ -20,17 +18,14 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
*
|
||||
*/
|
||||
public abstract class DSpaceObjectRest extends BaseObjectRest<String> {
|
||||
@JsonIgnore
|
||||
private String uuid;
|
||||
|
||||
private String name;
|
||||
private String handle;
|
||||
private String type;
|
||||
|
||||
List<MetadataEntryRest> metadata;
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public String getId() {
|
||||
return uuid;
|
||||
}
|
||||
@@ -68,7 +63,6 @@ public abstract class DSpaceObjectRest extends BaseObjectRest<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
@@ -12,8 +12,6 @@ import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* The EPerson REST Resource
|
||||
*
|
||||
@@ -22,7 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
*/
|
||||
public class EPersonRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "eperson";
|
||||
|
||||
public static final String CATEGORY = RestModel.EPERSON;
|
||||
private String netid;
|
||||
|
||||
private Date lastActive;
|
||||
@@ -102,7 +100,11 @@ public class EPersonRest extends DSpaceObjectRest {
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
@@ -21,6 +21,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
*/
|
||||
public class GroupRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "group";
|
||||
|
||||
public static final String CATEGORY = RestModel.EPERSON;
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -31,6 +33,11 @@ public class GroupRest extends DSpaceObjectRest {
|
||||
// https://jira.duraspace.org/browse/DS-3483
|
||||
private List<GroupRest> groups;
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
|
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
*/
|
||||
public class ItemRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "item";
|
||||
public static final String CATEGORY = RestModel.CORE;
|
||||
private boolean inArchive = false;
|
||||
private boolean discoverable = false;
|
||||
private boolean withdrawn = false;
|
||||
@@ -32,6 +33,11 @@ public class ItemRest extends DSpaceObjectRest {
|
||||
|
||||
List<BitstreamRest> bitstreams;
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
|
@@ -19,7 +19,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
*/
|
||||
public class MetadataFieldRest extends BaseObjectRest<Integer> {
|
||||
public static final String NAME = "metadatafield";
|
||||
|
||||
public static final String CATEGORY = RestModel.CORE;
|
||||
|
||||
@JsonIgnore
|
||||
private MetadataSchemaRest schema;
|
||||
|
||||
@@ -67,8 +68,12 @@ public class MetadataFieldRest extends BaseObjectRest<Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
}
|
@@ -21,7 +21,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
*/
|
||||
public class MetadataSchemaRest extends BaseObjectRest<Integer> {
|
||||
public static final String NAME = "metadataschema";
|
||||
|
||||
public static final String CATEGORY = RestModel.CORE;
|
||||
|
||||
private String prefix;
|
||||
|
||||
private String namespace;
|
||||
@@ -48,8 +49,12 @@ public class MetadataSchemaRest extends BaseObjectRest<Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
}
|
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* Methods to implement to make a REST resource addressable
|
||||
*
|
||||
@@ -14,7 +16,15 @@ package org.dspace.app.rest.model;
|
||||
*
|
||||
*/
|
||||
public interface RestModel {
|
||||
public static final String CORE = "core";
|
||||
public static final String EPERSON = "eperson";
|
||||
public static final String DISCOVER = "discover";
|
||||
|
||||
@JsonIgnore
|
||||
public String getCategory();
|
||||
|
||||
public String getType();
|
||||
|
||||
@JsonIgnore
|
||||
public Class getController();
|
||||
}
|
||||
|
@@ -15,7 +15,13 @@ package org.dspace.app.rest.model;
|
||||
*/
|
||||
public class SiteRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "site";
|
||||
|
||||
public static final String CATEGORY = RestModel.CORE;
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
|
@@ -55,11 +55,12 @@ public abstract class DSpaceResource<T extends RestModel> extends ResourceSuppor
|
||||
RestModel linkedObject = (RestModel) readMethod.invoke(data);
|
||||
if (linkedObject != null) {
|
||||
embedded.put(pd.getName(),
|
||||
utils.getResourceRepository(linkedObject.getType()).wrapResource(linkedObject));
|
||||
utils.getResourceRepository(linkedObject.getCategory(), linkedObject.getType())
|
||||
.wrapResource(linkedObject));
|
||||
} else {
|
||||
embedded.put(pd.getName(), null);
|
||||
}
|
||||
|
||||
|
||||
Method writeMethod = pd.getWriteMethod();
|
||||
writeMethod.invoke(data, new Object[] { null });
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ import org.springframework.stereotype.Component;
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component(BitstreamFormatRest.NAME)
|
||||
@Component(BitstreamFormatRest.CATEGORY + "." + BitstreamFormatRest.NAME)
|
||||
public class BitstreamFormatRestRepository extends DSpaceRestRepository<BitstreamFormatRest, Integer> {
|
||||
BitstreamFormatService bfs = ContentServiceFactory.getInstance().getBitstreamFormatService();
|
||||
@Autowired
|
||||
|
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(BitstreamRest.NAME)
|
||||
@Component(BitstreamRest.CATEGORY + "." + BitstreamRest.NAME)
|
||||
public class BitstreamRestRepository extends DSpaceRestRepository<BitstreamRest, UUID> {
|
||||
BitstreamService bs = ContentServiceFactory.getInstance().getBitstreamService();
|
||||
@Autowired
|
||||
|
@@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(CollectionRest.NAME)
|
||||
@Component(CollectionRest.CATEGORY + "." + CollectionRest.NAME)
|
||||
public class CollectionRestRepository extends DSpaceRestRepository<CollectionRest, UUID> {
|
||||
CollectionService cs = ContentServiceFactory.getInstance().getCollectionService();
|
||||
@Autowired
|
||||
|
@@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(CommunityRest.NAME)
|
||||
@Component(CommunityRest.CATEGORY + "." + CommunityRest.NAME)
|
||||
public class CommunityRestRepository extends DSpaceRestRepository<CommunityRest, UUID> {
|
||||
CommunityService cs = ContentServiceFactory.getInstance().getCommunityService();
|
||||
@Autowired
|
||||
|
@@ -31,7 +31,7 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(EPersonRest.NAME)
|
||||
@Component(EPersonRest.CATEGORY + "." + EPersonRest.NAME)
|
||||
public class EPersonRestRepository extends DSpaceRestRepository<EPersonRest, UUID> {
|
||||
EPersonService es = EPersonServiceFactory.getInstance().getEPersonService();
|
||||
|
||||
|
@@ -31,7 +31,7 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(GroupRest.NAME)
|
||||
@Component(GroupRest.CATEGORY + "." + GroupRest.NAME)
|
||||
public class GroupRestRepository extends DSpaceRestRepository<GroupRest, UUID> {
|
||||
GroupService gs = EPersonServiceFactory.getInstance().getGroupService();
|
||||
|
||||
|
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(ItemRest.NAME)
|
||||
@Component(ItemRest.CATEGORY + "." + ItemRest.NAME)
|
||||
public class ItemRestRepository extends DSpaceRestRepository<ItemRest, UUID> {
|
||||
ItemService is = ContentServiceFactory.getInstance().getItemService();
|
||||
@Autowired
|
||||
|
@@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
*/
|
||||
|
||||
@Component(SiteRest.NAME)
|
||||
@Component(SiteRest.CATEGORY + "." + SiteRest.NAME)
|
||||
public class SiteRestRepository extends DSpaceRestRepository<SiteRest, UUID> {
|
||||
SiteService sitesv = ContentServiceFactory.getInstance().getSiteService();
|
||||
@Autowired
|
||||
|
@@ -59,19 +59,19 @@ public class Utils {
|
||||
}
|
||||
|
||||
public Link linkToSingleResource(RestModel data, String rel) {
|
||||
return linkTo(data.getController(), data.getType()).slash(data).withRel(rel);
|
||||
return linkTo(data.getController(), data.getCategory(), data.getType()).slash(data).withRel(rel);
|
||||
}
|
||||
|
||||
public Link linkToSubResource(RestModel data, String rel) {
|
||||
return linkTo(data.getController(), data.getType()).slash(data).slash(rel).withRel(rel);
|
||||
return linkTo(data.getController(), data.getCategory(), data.getType()).slash(data).slash(rel).withRel(rel);
|
||||
}
|
||||
|
||||
public DSpaceRestRepository getResourceRepository(String modelPlural) {
|
||||
public DSpaceRestRepository getResourceRepository(String apiCategory, String modelPlural) {
|
||||
String model = makeSingular(modelPlural);
|
||||
try {
|
||||
return applicationContext.getBean(model, DSpaceRestRepository.class);
|
||||
return applicationContext.getBean(apiCategory + "." + model, DSpaceRestRepository.class);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
throw new RepositoryNotFoundException(model);
|
||||
throw new RepositoryNotFoundException(apiCategory, model);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user