Skip to content

Commit

Permalink
Utils is now a singleton. DSpaceResource automatically adds links to …
Browse files Browse the repository at this point in the history
…embedded resources
  • Loading branch information
abollini committed Feb 12, 2017
1 parent b7ce038 commit 3a21c4b
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 71 deletions.
@@ -1,53 +1,40 @@
package org.dspace.app.rest;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;

import java.util.ArrayList;
import java.util.UUID;

import org.dspace.app.rest.exception.PaginationException;
import org.dspace.app.rest.exception.RepositoryNotFoundException;
import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.RestModel;
import org.dspace.app.rest.model.hateoas.DSpaceResource;
import org.dspace.app.rest.repository.BitstreamRestRepository;
import org.dspace.app.rest.repository.DSpaceRestRepository;
import org.dspace.app.rest.utils.Utils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PagedResourcesAssembler;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.PagedResources;
import org.springframework.hateoas.Resources;
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;

@RestController
//@ExposesResourceFor(BitstreamRest.class)
@RequestMapping("/api/core/{model}s")
@SuppressWarnings("rawtypes")
public class RestResourceController {

// @Autowired
// EntityLinks entityLinks;

@Autowired
ApplicationContext applicationContext;
Utils utils;

@RequestMapping(method = RequestMethod.GET, value = "/{uuid}")
@SuppressWarnings("unchecked")
DSpaceResource<BitstreamRest> findOne(@PathVariable String model, @PathVariable UUID uuid, @RequestParam(required=false) String projection) {
DSpaceRestRepository repository = getResourceRepository(model);
DSpaceRestRepository repository = utils.getResourceRepository(model);
RestModel modelObject = repository.findOne(uuid);
DSpaceResource result = repository.wrapResource(modelObject);
//Link link = entityLinks.linkFor(getResourceClass(model), model, uuid).withSelfRel();
Expand All @@ -59,7 +46,7 @@ DSpaceResource<BitstreamRest> findOne(@PathVariable String model, @PathVariable
@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 = getResourceRepository(model);
DSpaceRestRepository<T, ?> repository = utils.getResourceRepository(model);
// Link link = entityLinks.linkFor(getResourceClass(model), model, page).withSelfRel();
Link link = linkTo(this.getClass(), model).withSelfRel();

Expand All @@ -76,16 +63,4 @@ <T extends RestModel> PagedResources<DSpaceResource<T>> findAll(@PathVariable St
PagedResources<DSpaceResource<T>> result = assembler.toResource(resources, link);
return result;
}

private Class<?> getResourceClass(String model) {
return getResourceRepository(model).getDomainClass();
}

private DSpaceRestRepository getResourceRepository(String model) {
try {
return applicationContext.getBean(model, DSpaceRestRepository.class);
} catch (NoSuchBeanDefinitionException e) {
throw new RepositoryNotFoundException(model);
}
}
}
Expand Up @@ -14,6 +14,8 @@ public class BitstreamRest extends DSpaceObjectRest {
public static final String NAME = "bitstream";
private String bundleName;

// avoid to serialize this object inline as we want a full resource embedded
//TODO extends this annotation to provide information about lazy loading and projection behavior
@JsonProperty(access=Access.WRITE_ONLY)
private BitstreamFormatRest format;
private Long sizeBytes;
Expand Down
@@ -1,10 +1,11 @@
package org.dspace.app.rest.model.hateoas;

import org.dspace.app.rest.model.BitstreamFormatRest;
import org.dspace.app.rest.utils.Utils;

@RelNameDSpaceResource(BitstreamFormatRest.NAME)
public class BitstreamFormatResource extends DSpaceResource<BitstreamFormatRest> {
public BitstreamFormatResource(BitstreamFormatRest bf) {
super(bf);
public BitstreamFormatResource(BitstreamFormatRest bf, Utils utils) {
super(bf, utils);
}
}
@@ -1,12 +1,12 @@
package org.dspace.app.rest.model.hateoas;

import org.dspace.app.rest.model.BitstreamRest;
import org.springframework.hateoas.Link;
import org.dspace.app.rest.utils.Utils;

@RelNameDSpaceResource(BitstreamRest.NAME)
public class BitstreamResource extends DSpaceResource<BitstreamRest> {
public BitstreamResource(BitstreamRest bs) {
super(bs);
public BitstreamResource(BitstreamRest bs, Utils utils) {
super(bs, utils);
// if (bs.getFormat() != null) {
// BitstreamFormatResource bfr = new BitstreamFormatResource(bs.getFormat());
// this.add(new Link(bfr.getLink(Link.REL_SELF).getHref(), "bitstreamformat"));
Expand Down
Expand Up @@ -13,39 +13,52 @@
import org.springframework.hateoas.Link;
import org.springframework.hateoas.ResourceSupport;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonUnwrapped;

public abstract class DSpaceResource<T extends RestModel> extends ResourceSupport {
@JsonUnwrapped
private final T data;

private Map<String, Object> _embedded = new HashMap<String, Object>();

public DSpaceResource(T data) {
@JsonProperty(value="_embedded")
@JsonInclude(Include.NON_EMPTY)
private Map<String, Object> embedded = new HashMap<String, Object>();

public DSpaceResource(T data, Utils utils) {
this.data = data;

try {
for (PropertyDescriptor pd : Introspector.getBeanInfo(data.getClass()).getPropertyDescriptors()) {
Method readMethod = pd.getReadMethod();
if (readMethod != null && !"class".equals(pd.getName())) {
if (RestModel.class.isAssignableFrom(readMethod.getReturnType())) {
this.add(Utils.linkToSubResource(data, pd.getName()));
_embedded.put(pd.getName(), readMethod.invoke(data));
// Method writeMethod = pd.getWriteMethod();
// writeMethod.invoke(data, new Object[]{null});
this.add(utils.linkToSubResource(data, pd.getName()));
RestModel linkedObject = (RestModel) readMethod.invoke(data);
if (linkedObject != null) {
embedded.put(pd.getName(),
utils.getResourceRepository(linkedObject.getType()).wrapResource(linkedObject));
} else {
embedded.put(pd.getName(), null);
}

Method writeMethod = pd.getWriteMethod();
writeMethod.invoke(data, new Object[] { null });
}
}
}
} catch (IntrospectionException | IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
} catch (IntrospectionException | IllegalArgumentException | IllegalAccessException
| InvocationTargetException e) {
throw new RuntimeException(e.getMessage(), e);
}
this.add(Utils.linkToSingleResource(data, Link.REL_SELF));
this.add(utils.linkToSingleResource(data, Link.REL_SELF));
}

public Map<String, Object> get_embedded() {
return _embedded;
public Map<String, Object> getEmbedded() {
return embedded;
}

public T getData() {
return data;
}
Expand Down
@@ -1,10 +1,11 @@
package org.dspace.app.rest.model.hateoas;

import org.dspace.app.rest.model.ItemRest;
import org.dspace.app.rest.utils.Utils;

@RelNameDSpaceResource(ItemRest.NAME)
public class ItemResource extends DSpaceResource<ItemRest> {
public ItemResource(ItemRest item) {
super(item);
public ItemResource(ItemRest item, Utils utils) {
super(item, utils);
}
}
Expand Up @@ -49,7 +49,7 @@ public Page<BitstreamFormatRest> findAll(Context context, Pageable pageable) {
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
Page<BitstreamFormatRest> page = Utils.getPage(bit, pageable).map(converter);
Page<BitstreamFormatRest> page = utils.getPage(bit, pageable).map(converter);
return page;
}

Expand All @@ -60,6 +60,6 @@ public Class<BitstreamFormatRest> getDomainClass() {

@Override
public BitstreamFormatResource wrapResource(BitstreamFormatRest bs) {
return new BitstreamFormatResource(bs);
return new BitstreamFormatResource(bs, utils);
}
}
Expand Up @@ -59,6 +59,6 @@ public Class<BitstreamRest> getDomainClass() {

@Override
public BitstreamResource wrapResource(BitstreamRest bs) {
return new BitstreamResource(bs);
return new BitstreamResource(bs, utils);
}
}
Expand Up @@ -5,10 +5,13 @@
import org.dspace.app.rest.model.RestModel;
import org.dspace.app.rest.model.hateoas.DSpaceResource;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.core.Context;
import org.dspace.services.RequestService;
import org.dspace.services.model.Request;
import org.dspace.utils.DSpace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
Expand All @@ -19,10 +22,13 @@
* @author Andrea Bollini (andrea.bollini at 4science.it)
*
*/
public abstract class DSpaceRestRepository<T extends RestModel, ID extends Serializable> implements PagingAndSortingRepository<T, ID> {
public abstract class DSpaceRestRepository<T extends RestModel, ID extends Serializable>
implements PagingAndSortingRepository<T, ID> {
@Autowired
protected Utils utils;

protected RequestService requestService = new DSpace().getRequestService();

@Override
public <S extends T> S save(S entity) {
// TODO Auto-generated method stub
Expand Down Expand Up @@ -68,25 +74,25 @@ public long count() {
@Override
public void delete(ID id) {
// TODO Auto-generated method stub

}

@Override
public void delete(T entity) {
// TODO Auto-generated method stub

}

@Override
public void delete(Iterable<? extends T> entities) {
// TODO Auto-generated method stub

}

@Override
public void deleteAll() {
// TODO Auto-generated method stub

}

@Override
Expand All @@ -99,9 +105,9 @@ public Page<T> findAll(Pageable pageable) {
Context context = obtainContext();
return findAll(context, pageable);
}

public abstract Page<T> findAll(Context context, Pageable pageable);

private Context obtainContext() {
Request currentRequest = requestService.getCurrentRequest();
Context context = (Context) currentRequest.getAttribute(ContextUtil.DSPACE_CONTEXT);
Expand All @@ -114,6 +120,6 @@ private Context obtainContext() {
}

public abstract Class<T> getDomainClass();

public abstract DSpaceResource<T> wrapResource(T model);
}
Expand Up @@ -67,7 +67,7 @@ public Class<ItemRest> getDomainClass() {

@Override
public ItemResource wrapResource(ItemRest item) {
return new ItemResource(item);
return new ItemResource(item, utils);
}

}
Expand Up @@ -4,13 +4,10 @@
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.web.config.EnableSpringDataWebSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;

@Configuration
@EnableSpringDataWebSupport
@EnableHypermediaSupport(type={HypermediaType.HAL})
@ComponentScan({ "org.dspace.app.rest.converter", "org.dspace.app.rest.repository" })
@ComponentScan({ "org.dspace.app.rest.converter", "org.dspace.app.rest.repository", "org.dspace.app.rest.utils" })
public class ApplicationConfig {
@Value("${dspace.dir}")
private String dspaceHome;
Expand Down
Expand Up @@ -5,17 +5,25 @@
import java.util.List;

import org.dspace.app.rest.exception.PaginationException;
import org.dspace.app.rest.exception.RepositoryNotFoundException;
import org.dspace.app.rest.model.RestModel;
import org.dspace.app.rest.model.hateoas.DSpaceResource;
import org.dspace.app.rest.repository.DSpaceRestRepository;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
import org.springframework.stereotype.Component;

@Component
public class Utils {
@Autowired
ApplicationContext applicationContext;

public static <T> Page<T> getPage(List<T> fullContents, Pageable pageable) {
public <T> Page<T> getPage(List<T> fullContents, Pageable pageable) {
int total = fullContents.size();
List<T> pageContent = null;
if (pageable.getOffset() > total) {
Expand All @@ -32,16 +40,24 @@ public static <T> Page<T> getPage(List<T> fullContents, Pageable pageable) {
}
}

public static Link linkToSingleResource(DSpaceResource r, String rel) {
public Link linkToSingleResource(DSpaceResource r, String rel) {
RestModel data = r.getData();
return linkToSingleResource(data, rel);
}

public static Link linkToSingleResource(RestModel data, String rel) {
public Link linkToSingleResource(RestModel data, String rel) {
return linkTo(data.getController(), data.getType()).slash(data).withRel(rel);
}

public static Link linkToSubResource(RestModel data, String rel) {
public Link linkToSubResource(RestModel data, String rel) {
return linkTo(data.getController(), data.getType()).slash(data).slash(rel).withRel(rel);
}

public DSpaceRestRepository getResourceRepository(String model) {
try {
return applicationContext.getBean(model, DSpaceRestRepository.class);
} catch (NoSuchBeanDefinitionException e) {
throw new RepositoryNotFoundException(model);
}
}
}

0 comments on commit 3a21c4b

Please sign in to comment.