Merge pull request #2302 from atmire/w2p-57441_modified-behavior-retrieving-relations

Retrieving relations per relationship type
This commit is contained in:
benbosman
2019-01-29 14:25:35 +01:00
committed by GitHub
20 changed files with 1013 additions and 19 deletions

View File

@@ -49,6 +49,7 @@ public class RelationshipServiceImpl implements RelationshipService {
return relationshipDAO.create(context, new Relationship());
}
@Override
public Relationship create(Context context, Relationship relationship) throws SQLException, AuthorizeException {
if (isRelationshipValidToCreate(context, relationship)) {
if (!authorizeService.isAdmin(context)) {
@@ -93,10 +94,12 @@ public class RelationshipServiceImpl implements RelationshipService {
}
}
@Override
public int findLeftPlaceByLeftItem(Context context, Item item) throws SQLException {
return relationshipDAO.findLeftPlaceByLeftItem(context, item);
}
@Override
public int findRightPlaceByRightItem(Context context, Item item) throws SQLException {
return relationshipDAO.findRightPlaceByRightItem(context, item);
}
@@ -172,6 +175,7 @@ public class RelationshipServiceImpl implements RelationshipService {
return relationship;
}
@Override
public List<Relationship> findByItem(Context context, Item item) throws SQLException {
List<Relationship> list = relationshipDAO.findByItem(context, item);
@@ -192,6 +196,7 @@ public class RelationshipServiceImpl implements RelationshipService {
return list;
}
@Override
public List<Relationship> findAll(Context context) throws SQLException {
return relationshipDAO.findAll(context, Relationship.class);
}
@@ -299,6 +304,7 @@ public class RelationshipServiceImpl implements RelationshipService {
@Override
public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType)
throws SQLException {
List<Relationship> list = this.findByItem(context, item);
List<Relationship> listToReturn = new LinkedList<>();
@@ -309,4 +315,10 @@ public class RelationshipServiceImpl implements RelationshipService {
}
return listToReturn;
}
@Override
public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType)
throws SQLException {
return relationshipDAO.findByRelationshipType(context, relationshipType);
}
}

View File

@@ -35,6 +35,7 @@ public class RelationshipTypeServiceImpl implements RelationshipTypeService {
return relationshipTypeDAO.create(context, new RelationshipType());
}
@Override
public RelationshipType create(Context context, RelationshipType relationshipType)
throws SQLException, AuthorizeException {
if (!authorizeService.isAdmin(context)) {
@@ -44,15 +45,27 @@ public class RelationshipTypeServiceImpl implements RelationshipTypeService {
return relationshipTypeDAO.create(context, relationshipType);
}
@Override
public RelationshipType findbyTypesAndLabels(Context context,EntityType leftType,EntityType rightType,
String leftLabel,String rightLabel) throws SQLException {
return relationshipTypeDAO.findbyTypesAndLabels(context, leftType, rightType, leftLabel, rightLabel);
}
@Override
public List<RelationshipType> findAll(Context context) throws SQLException {
return relationshipTypeDAO.findAll(context, RelationshipType.class);
}
@Override
public List<RelationshipType> findByLeftOrRightLabel(Context context, String label) throws SQLException {
return relationshipTypeDAO.findByLeftOrRightLabel(context, label);
}
@Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException {
return relationshipTypeDAO.findByEntityType(context, entityType);
}
public RelationshipType find(Context context,int id) throws SQLException {
return relationshipTypeDAO.findByID(context, RelationshipType.class, id);
}
@@ -84,9 +97,4 @@ public class RelationshipTypeServiceImpl implements RelationshipTypeService {
}
relationshipTypeDAO.delete(context, relationshipType);
}
@Override
public List<RelationshipType> findByLeftOrRightLabel(Context context, String label) throws SQLException {
return relationshipTypeDAO.findByLeftOrRightLabel(context, label);
}
}

View File

@@ -12,6 +12,7 @@ import java.util.List;
import org.dspace.content.Item;
import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType;
import org.dspace.core.Context;
import org.dspace.core.GenericDAO;
@@ -56,4 +57,16 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
* @throws SQLException If something goes wrong
*/
int findRightPlaceByRightItem(Context context,Item item) throws SQLException;
/**
* This method returns a list of Relationship objects for the given RelationshipType object.
* It will construct a list of all Relationship objects that have the given RelationshipType object
* as the relationshipType property
* @param context The relevant DSpace context
* @param relationshipType The RelationshipType object to be checked on
* @return A list of Relationship objects that have the given RelationshipType object as the
* relationshipType property
* @throws SQLException If something goes wrong
*/
List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType) throws SQLException;
}

View File

@@ -39,13 +39,23 @@ public interface RelationshipTypeDAO extends GenericDAO<RelationshipType> {
throws SQLException;
/**
* This method will query the Database for a list of RelationshipType objects that have the given label
* either as a left or right label in its attributes
* This method will return a list of RelationshipType objects for which the given label is equal to
* either the leftLabel or rightLabel.
* @param context The relevant DSpace context
* @param label The label that the RelationshipType must have as a leftLabel or rightLabel attribute
* @return The list of RelationshipType objects that fit the criteria
* @param label The label that will be used to check on
* @return A list of RelationshipType objects that have the given label as either the leftLabel or rightLabel
* @throws SQLException If something goes wrong
*/
List<RelationshipType> findByLeftOrRightLabel(Context context, String label) throws SQLException;
/**
* This method will return a list of RelationshipType objects for which the given EntityType object is equal
* to the leftType or rightType
* @param context The relevant DSpace context
* @param entityType The EntityType object that will be used to check on
* @return The list of RelationshipType objects that have the given EntityType object
* as either a leftType or rightType
* @throws SQLException If something goes wrong
*/
List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException;
}

View File

@@ -15,6 +15,7 @@ import javax.persistence.criteria.Root;
import org.dspace.content.Item;
import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType;
import org.dspace.content.Relationship_;
import org.dspace.content.dao.RelationshipDAO;
import org.dspace.core.AbstractHibernateDAO;
@@ -22,6 +23,7 @@ import org.dspace.core.Context;
public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> implements RelationshipDAO {
@Override
public List<Relationship> findByItem(Context context, Item item) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
@@ -33,6 +35,7 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
return list(context, criteriaQuery, false, Relationship.class, -1, -1);
}
@Override
public int findLeftPlaceByLeftItem(Context context, Item item) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
@@ -48,6 +51,7 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
}
}
@Override
public int findRightPlaceByRightItem(Context context, Item item) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
@@ -62,4 +66,18 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
return 1;
}
}
@Override
public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType)
throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.select(relationshipRoot);
criteriaQuery
.where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType), relationshipType));
return list(context, criteriaQuery, true, Relationship.class, -1, -1);
}
}

View File

@@ -22,6 +22,7 @@ import org.dspace.core.Context;
public class RelationshipTypeDAOImpl extends AbstractHibernateDAO<RelationshipType> implements RelationshipTypeDAO {
@Override
public RelationshipType findbyTypesAndLabels(Context context, EntityType leftType, EntityType rightType,
String leftLabel, String rightLabel)
throws SQLException {
@@ -53,4 +54,20 @@ public class RelationshipTypeDAOImpl extends AbstractHibernateDAO<RelationshipTy
return list(context, criteriaQuery, true, RelationshipType.class, -1, -1);
}
@Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class);
Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class);
criteriaQuery.select(relationshipTypeRoot);
criteriaQuery.where(
criteriaBuilder.or(criteriaBuilder.
equal(relationshipTypeRoot.get(RelationshipType_.leftType), entityType),
criteriaBuilder
.equal(relationshipTypeRoot.get(RelationshipType_.rightType), entityType)
)
);
return list(context, criteriaQuery, false, RelationshipType.class, -1, -1);
}
}

View File

@@ -74,17 +74,27 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
int findRightPlaceByRightItem(Context context, Item item) throws SQLException;
/**
* This method will retrieve a list of Relationship objects by retrieving the list of Relationship objects
* for the given item and then filtering the Relationship objects on the RelationshipType object that is
* passed along to this method.
* This method returns a list of Relationships for which the leftItem or rightItem is equal to the given
* Item object and for which the RelationshipType object is equal to the relationshipType property
* @param context The relevant DSpace context
* @param item The Item for which the list of Relationship objects will be retrieved
* @param relationshipType The RelationshipType object on which the list of Relationship objects for the given
* Item will be filtered
* @return The list of Relationship objects for the given Item filtered on the RelationshipType object
* @param item The Item object to be matched on the leftItem or rightItem for the relationship
* @param relationshipType The RelationshipType object that will be used to check the Relationship on
* @return The list of Relationship objects that have the given Item object as leftItem or rightItem and
* for which the relationshipType property is equal to the given RelationshipType
* @throws SQLException If something goes wrong
*/
public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType)
throws SQLException;
/**
* This method returns a list of Relationship objets for which the relationshipType property is equal to the given
* RelationshipType object
* @param context The relevant DSpace context
* @param relationshipType The RelationshipType object that will be used to check the Relationship on
* @return The list of Relationship objects for which the given RelationshipType object is equal
* to the relationshipType property
* @throws SQLException If something goes wrong
*/
List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType) throws SQLException;
}

View File

@@ -63,4 +63,15 @@ public interface RelationshipTypeService extends DSpaceCRUDService<RelationshipT
* @throws SQLException If something goes wrong
*/
List<RelationshipType> findByLeftOrRightLabel(Context context, String label) throws SQLException;
/**
* Returns a list of RelationshipType objects for which the given EntityType is equal to either the leftType
* or the rightType
* @param context The relevant DSpace context
* @param entityType The EntityType object used to check the leftType and rightType properties
* @return A list of RelationshipType objects for which the leftType or rightType property are equal to the
* given EntityType object
* @throws SQLException If something goes wrong
*/
List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException;
}

View File

@@ -109,4 +109,17 @@
<min>0</min>
</rightCardinality>
</type>
<type>
<leftType>JournalIssue</leftType>
<rightType>Publication</rightType>
<leftLabel>isPublicationOfJournalIssue</leftLabel>
<rightLabel>isJournalIssueOfPublication</rightLabel>
<leftCardinality>
<min>0</min>
</leftCardinality>
<rightCardinality>
<min>0</min>
<max>1</max>
</rightCardinality>
</type>
</relationships>

View File

@@ -0,0 +1,133 @@
/**
* 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.util.LinkedList;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.converter.RelationshipConverter;
import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.RelationshipRest;
import org.dspace.app.rest.model.RelationshipRestWrapper;
import org.dspace.app.rest.model.hateoas.RelationshipResourceWrapper;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.content.Item;
import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.core.Context;
import org.dspace.util.UUIDUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
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;
/**
* This will be the entry point for the api/core/relationships endpoint with additional paths to it
*/
@RestController
@RequestMapping("/api/core/relationships")
public class RelationshipRestController {
/**
* Regular expression in the request mapping to accept a string as identifier but not the other kind of
* identifier (digits or uuid)
*/
private static final String REGEX_REQUESTMAPPING_LABEL = "/{label:^(?!^\\d+$)" +
"(?!^[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}$)[\\w+\\-]+$+}";
@Autowired
private RelationshipTypeService relationshipTypeService;
@Autowired
private RelationshipService relationshipService;
@Autowired
private ItemService itemService;
@Autowired
private RelationshipConverter relationshipConverter;
@Autowired
Utils utils;
@Autowired
private HalLinkService halLinkService;
/**
* This method will retrieve all the Relationships that have a RelationshipType which has a left or right label
* equal to the one passed along in the pathvariable.
* This is further filtered by an optional dso parameter to filter on only the relationships for the given dso
* if this is applicable
*
* @param response The response object
* @param request The request object
* @param label The label on which the Relationship's RelationshipType will be matched
* @param dsoId The ID of the dso on which we'll search for relationships if applicable
* @param pageable The page object
* @return A Resource containing all the relationships that meet the criteria
* @throws Exception If something goes wrong
*/
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_LABEL)
public RelationshipResourceWrapper retrieveByLabel(HttpServletResponse response,
HttpServletRequest request, @PathVariable String label,
@RequestParam(name = "dso", required = false) String dsoId,
Pageable pageable)
throws Exception {
Context context = ContextUtil.obtainContext(request);
List<RelationshipType> relationshipTypeList = relationshipTypeService.findByLeftOrRightLabel(context, label);
List<Relationship> relationships = new LinkedList<>();
if (StringUtils.isNotBlank(dsoId)) {
UUID uuid = UUIDUtils.fromString(dsoId);
Item item = itemService.find(context, uuid);
if (item == null) {
throw new ResourceNotFoundException("The request DSO with id: " + dsoId + " was not found");
}
for (RelationshipType relationshipType : relationshipTypeList) {
relationships.addAll(relationshipService.findByItemAndRelationshipType(context,
item, relationshipType));
}
} else {
for (RelationshipType relationshipType : relationshipTypeList) {
relationships.addAll(relationshipService.findByRelationshipType(context, relationshipType));
}
}
List<RelationshipRest> relationshipRests = new LinkedList<>();
for (Relationship relationship : relationships) {
relationshipRests.add(relationshipConverter.fromModel(relationship));
}
RelationshipRestWrapper relationshipRestWrapper = new RelationshipRestWrapper();
relationshipRestWrapper.setLabel(label);
relationshipRestWrapper.setDsoId(dsoId);
relationshipRestWrapper.setRelationshipRestList(relationshipRests);
RelationshipResourceWrapper relationshipResourceWrapper = new RelationshipResourceWrapper(
relationshipRestWrapper, utils, relationshipRests.size(), pageable);
halLinkService.addLinks(relationshipResourceWrapper, pageable);
return relationshipResourceWrapper;
}
}

View File

@@ -0,0 +1,93 @@
/**
* 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.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.converter.RelationshipTypeConverter;
import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.RelationshipTypeRest;
import org.dspace.app.rest.model.RelationshipTypeRestWrapper;
import org.dspace.app.rest.model.hateoas.RelationshipTypeResourceWrapper;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.content.EntityType;
import org.dspace.content.RelationshipType;
import org.dspace.content.service.EntityTypeService;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* This controller will handle all the incoming calls on the api/core/entitytypes/{id}/relationshiptypes endpoint
* where the id parameter can be filled in to match a specific entityType and then get all the relationshipTypes
* for the given EntityType
*/
@RestController
@RequestMapping("/api/core/entitytypes/{id}/relationshiptypes")
public class RelationshipTypeRestController {
@Autowired
private RelationshipTypeService relationshipTypeService;
@Autowired
private EntityTypeService entityTypeService;
@Autowired
private RelationshipTypeConverter relationshipTypeConverter;
@Autowired
private Utils utils;
@Autowired
private HalLinkService halLinkService;
/**
* This method will retrieve all the RelationshipTypes that conform to the given EntityType by the given ID and
* it will return this in a wrapped resource.
*
* @param id The ID of the EntityType objects that we'll use to retrieve the RelationshipTypes
* @param response The response object
* @param request The request object
* @return The wrapped resource containing the list of RelationshipType objects as defined above
* @throws SQLException If something goes wrong
*/
@RequestMapping(method = RequestMethod.GET)
public RelationshipTypeResourceWrapper retrieve(@PathVariable Integer id, HttpServletResponse response,
HttpServletRequest request) throws SQLException {
Context context = ContextUtil.obtainContext(request);
EntityType entityType = entityTypeService.find(context, id);
List<RelationshipType> list = relationshipTypeService.findByEntityType(context, entityType);
List<RelationshipTypeRest> relationshipTypeRests = new LinkedList<>();
for (RelationshipType relationshipType : list) {
relationshipTypeRests.add(relationshipTypeConverter.fromModel(relationshipType));
}
RelationshipTypeRestWrapper relationshipTypeRestWrapper = new RelationshipTypeRestWrapper();
relationshipTypeRestWrapper.setEntityTypeId(id);
relationshipTypeRestWrapper.setEntityTypeLabel(entityType.getLabel());
relationshipTypeRestWrapper.setRelationshipTypeRestList(relationshipTypeRests);
RelationshipTypeResourceWrapper relationshipTypeResourceWrapper = new RelationshipTypeResourceWrapper(
relationshipTypeRestWrapper, utils);
halLinkService.addLinks(relationshipTypeResourceWrapper);
return relationshipTypeResourceWrapper;
}
}

View File

@@ -0,0 +1,42 @@
/**
* 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.link.relation;
import java.util.LinkedList;
import org.dspace.app.rest.RelationshipTypeRestController;
import org.dspace.app.rest.link.HalLinkFactory;
import org.dspace.app.rest.model.hateoas.EntityTypeResource;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link;
import org.springframework.stereotype.Component;
/**
* This class' purpose is to add the links to the EntityTypeResource. This function and class will be called
* and used
* when the HalLinkService addLinks methods is called as it'll iterate over all the different factories and check
* whether
* these are allowed to create links for said resource or not.
*/
@Component
public class EntityTypeHalLinkFactory extends HalLinkFactory<EntityTypeResource, RelationshipTypeRestController> {
@Override
protected void addLinks(EntityTypeResource halResource, Pageable pageable, LinkedList<Link> list) throws Exception {
list.add(buildLink("relationshiptypes", getMethodOn().retrieve(halResource.getContent().getId(), null, null)));
}
@Override
protected Class<RelationshipTypeRestController> getControllerClass() {
return RelationshipTypeRestController.class;
}
@Override
protected Class<EntityTypeResource> getResourceClass() {
return EntityTypeResource.class;
}
}

View File

@@ -0,0 +1,75 @@
/**
* 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.link.relation;
import java.util.LinkedList;
import org.dspace.app.rest.RelationshipRestController;
import org.dspace.app.rest.link.HalLinkFactory;
import org.dspace.app.rest.model.RelationshipRest;
import org.dspace.app.rest.model.RelationshipRestWrapper;
import org.dspace.app.rest.model.hateoas.EmbeddedPage;
import org.dspace.app.rest.model.hateoas.RelationshipResourceWrapper;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
/**
* This class' purpose is to add the links to the RelationshipResourceWrapper. This function and class will be called
* and used
* when the HalLinkService addLinks methods is called as it'll iterate over all the different factories and check
* whether
* these are allowed to create links for said resource or not.
*/
@Component
public class RelationshipResourceWrapperHalLinkFactory
extends HalLinkFactory<RelationshipResourceWrapper, RelationshipRestController> {
@Override
protected void addLinks(RelationshipResourceWrapper halResource, Pageable pageable, LinkedList<Link> list)
throws Exception {
PageImpl<RelationshipRest> page = new PageImpl<>(halResource.getContent().getRelationshipRestList(), pageable,
halResource.getContent().getRelationshipRestList().size());
halResource.setPageHeader(new EmbeddedPage(getSelfLink(halResource.getContent(), pageable),
page, halResource.getContent().getRelationshipRestList(),
true, "relationships"));
}
/**
* This method will construct a self link to the RelationshipRestController.retrieveByLabel method.
* This will be constructed so that the RelationshipResourceWrapper resource can contain this selflink
* and immediately point to the correct endpoint with it.
* @param content The RelationshipRestWrapper from which we'll retrieve variables to construct the link
* @param pageable The page object
* @return The String determining the link to the correct endpoint
* @throws Exception If something goes wrong
*/
public String getSelfLink(RelationshipRestWrapper content, Pageable pageable) throws Exception {
if (content != null) {
UriComponentsBuilder uriBuilderSelfLink = uriBuilder(getMethodOn()
.retrieveByLabel(null, null,
content.getLabel(),
content.getDsoId(), pageable));
return uriBuilderSelfLink.build().toString();
}
return null;
}
@Override
protected Class<RelationshipRestController> getControllerClass() {
return RelationshipRestController.class;
}
@Override
protected Class<RelationshipResourceWrapper> getResourceClass() {
return RelationshipResourceWrapper.class;
}
}

View File

@@ -0,0 +1,45 @@
/**
* 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.link.relation;
import java.util.LinkedList;
import org.dspace.app.rest.RelationshipTypeRestController;
import org.dspace.app.rest.link.HalLinkFactory;
import org.dspace.app.rest.model.hateoas.RelationshipTypeResourceWrapper;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link;
import org.springframework.stereotype.Component;
/**
* This class' purpose is to add the links to the RelationshipTypeResourceWrapper.
* This function and class will be called and used
* when the HalLinkService addLinks methods is called as it'll iterate over all the different factories and check
* whether
* these are allowed to create links for said resource or not.
*/
@Component
public class RelationshipTypeResourceWrapperHalLinkFactory
extends HalLinkFactory<RelationshipTypeResourceWrapper, RelationshipTypeRestController> {
@Override
protected void addLinks(RelationshipTypeResourceWrapper halResource, Pageable pageable, LinkedList<Link> list)
throws Exception {
list.add(buildLink(Link.REL_SELF, getMethodOn()
.retrieve(halResource.getContent().getEntityTypeId(), null, null)));
}
@Override
protected Class<RelationshipTypeRestController> getControllerClass() {
return RelationshipTypeRestController.class;
}
@Override
protected Class<RelationshipTypeResourceWrapper> getResourceClass() {
return RelationshipTypeResourceWrapper.class;
}
}

View File

@@ -0,0 +1,65 @@
/**
* 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.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.dspace.app.rest.RelationshipRestController;
/**
* This is the RestWrapper object for the RelationshipRestResource class. This will contain all the data that is
* used in that resource and more specifically, the label, dsoid and list of RelationshipRest objects
* The other methods are generic getters and setters
*/
public class RelationshipRestWrapper implements RestAddressableModel {
@JsonIgnore
private List<RelationshipRest> relationshipRestList;
private String label;
private String dsoId;
public List<RelationshipRest> getRelationshipRestList() {
return relationshipRestList;
}
public void setRelationshipRestList(List<RelationshipRest> relationshipRestList) {
this.relationshipRestList = relationshipRestList;
}
public String getCategory() {
return "core";
}
public Class getController() {
return RelationshipRestController.class;
}
public String getType() {
return "relationship";
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getDsoId() {
return dsoId;
}
public void setDsoId(String dsoId) {
this.dsoId = dsoId;
}
}

View File

@@ -0,0 +1,67 @@
/**
* 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.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.dspace.app.rest.RelationshipTypeRestController;
/**
* This is the RestWrapper object for the RelationshipTypeRestResource class. This will contain all the data that is
* used in that resource and more specifically, the entityTypeLabel, entityTypeId and list of
* RelationshipTypeRest objects
* The other methods are generic getters and setters
*/
public class RelationshipTypeRestWrapper implements RestAddressableModel {
@JsonIgnore
private List<RelationshipTypeRest> relationshipTypeRestList;
private String entityTypeLabel;
private Integer entityTypeId;
public List<RelationshipTypeRest> getRelationshipTypeRestList() {
return relationshipTypeRestList;
}
public void setRelationshipTypeRestList(
List<RelationshipTypeRest> relationshipTypeRestList) {
this.relationshipTypeRestList = relationshipTypeRestList;
}
public String getCategory() {
return "core";
}
public Class getController() {
return RelationshipTypeRestController.class;
}
public String getType() {
return "relationshiptype";
}
public String getEntityTypeLabel() {
return entityTypeLabel;
}
public void setEntityTypeLabel(String label) {
this.entityTypeLabel = label;
}
public Integer getEntityTypeId() {
return entityTypeId;
}
public void setEntityTypeId(Integer entityTypeId) {
this.entityTypeId = entityTypeId;
}
}

View File

@@ -0,0 +1,51 @@
/**
* 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.model.hateoas;
import java.util.LinkedList;
import java.util.List;
import org.dspace.app.rest.model.RelationshipRest;
import org.dspace.app.rest.model.RelationshipRestWrapper;
import org.dspace.app.rest.utils.Utils;
import org.springframework.data.domain.Pageable;
/**
* This is the RelationshipResourceWrapper class which will take the RelationshipRestWrapper's data and transform
* this into a resource with the data, embeds and links.
*/
public class RelationshipResourceWrapper extends HALResource<RelationshipRestWrapper> {
/**
* The constructor for the RelationshipResourceWrapper
* This will call the HALResource constructor and additionally add embeds to the resource
* @param content The RelationshipRestWrapper object that contains the data
* @param utils The Util object
* @param totalElements The total amount of elements to be included in the list
* @param pageable The pageable object
*/
public RelationshipResourceWrapper(RelationshipRestWrapper content, Utils utils, Integer totalElements,
Pageable pageable) {
super(content);
addEmbeds(content, utils, pageable);
}
private void addEmbeds(RelationshipRestWrapper content, Utils utils,
Pageable pageable) {
List<RelationshipResource> list = new LinkedList<>();
for (RelationshipRest relationshipRest : content.getRelationshipRestList()) {
list.add(new RelationshipResource(relationshipRest, utils));
}
int begin = pageable.getOffset();
int end = (pageable.getOffset() + pageable.getPageSize()) > list.size() ? list.size() :
pageable.getOffset() + pageable.getPageSize();
list = list.subList(begin, end);
embedResource("relationships", list);
}
}

View File

@@ -0,0 +1,42 @@
/**
* 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.model.hateoas;
import java.util.LinkedList;
import java.util.List;
import org.dspace.app.rest.model.RelationshipTypeRest;
import org.dspace.app.rest.model.RelationshipTypeRestWrapper;
import org.dspace.app.rest.utils.Utils;
/**
* This is the RelationshipTypeResourceWrapper class which will take the
* RelationshipTypeRestWrapper's data and transform this into a resource with the data, embeds and links.
*/
public class RelationshipTypeResourceWrapper extends HALResource<RelationshipTypeRestWrapper> {
/**
* The constructor for the RelationshipTypeResourceWrapper
* This will call the HALResource constructor and additionally add embeds to the resource
* @param content The RelationshipTypeRestWrapper object that contains the data
* @param utils The Util object
*/
public RelationshipTypeResourceWrapper(RelationshipTypeRestWrapper content, Utils utils) {
super(content);
addEmbeds(content, utils);
}
private void addEmbeds(RelationshipTypeRestWrapper content, Utils utils) {
List<RelationshipTypeResource> list = new LinkedList<>();
for (RelationshipTypeRest relationshipTypeRest : content.getRelationshipTypeRestList()) {
list.add(new RelationshipTypeResource(relationshipTypeRest, utils));
}
embedResource("relationshiptypes", list);
}
}

View File

@@ -0,0 +1,268 @@
/**
* 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.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import org.dspace.app.rest.builder.CollectionBuilder;
import org.dspace.app.rest.builder.CommunityBuilder;
import org.dspace.app.rest.builder.ItemBuilder;
import org.dspace.app.rest.builder.RelationshipBuilder;
import org.dspace.app.rest.matcher.EntityTypeMatcher;
import org.dspace.app.rest.matcher.PageMatcher;
import org.dspace.app.rest.matcher.RelationshipMatcher;
import org.dspace.app.rest.matcher.RelationshipTypeMatcher;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.EntityType;
import org.dspace.content.Item;
import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType;
import org.dspace.content.service.EntityTypeService;
import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.services.ConfigurationService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
public class RelationshipTypeRestControllerIT extends AbstractControllerIntegrationTest {
@Autowired
private RelationshipTypeService relationshipTypeService;
@Autowired
private EntityTypeService entityTypeService;
@Autowired
private RelationshipService relationshipService;
@Autowired
private ConfigurationService configurationService;
@Before
public void setup() throws Exception {
//Set up the database for the next test
String pathToFile = configurationService.getProperty("dspace.dir") +
File.separator + "config" + File.separator + "entities" + File.separator + "relationship-types.xml";
runDSpaceScript("initialize-entities", "-f", pathToFile);
}
@After
public void destroy() throws Exception {
//Clean up the database for the next test
context.turnOffAuthorisationSystem();
List<RelationshipType> relationshipTypeList = relationshipTypeService.findAll(context);
List<EntityType> entityTypeList = entityTypeService.findAll(context);
List<Relationship> relationships = relationshipService.findAll(context);
Iterator<Relationship> relationshipIterator = relationships.iterator();
while (relationshipIterator.hasNext()) {
Relationship relationship = relationshipIterator.next();
relationshipIterator.remove();
relationshipService.delete(context, relationship);
}
Iterator<RelationshipType> relationshipTypeIterator = relationshipTypeList.iterator();
while (relationshipTypeIterator.hasNext()) {
RelationshipType relationshipType = relationshipTypeIterator.next();
relationshipTypeIterator.remove();
relationshipTypeService.delete(context, relationshipType);
}
Iterator<EntityType> entityTypeIterator = entityTypeList.iterator();
while (entityTypeIterator.hasNext()) {
EntityType entityType = entityTypeIterator.next();
entityTypeIterator.remove();
entityTypeService.delete(context, entityType);
}
super.destroy();
}
@Test
public void findAllEntityTypes() throws Exception {
context.turnOffAuthorisationSystem();
getClient().perform(get("/api/core/entitytypes"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.page",
is(PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7))))
.andExpect(jsonPath("$._embedded.entitytypes", containsInAnyOrder(
EntityTypeMatcher.matchEntityTypeEntryForLabel("Publication"),
EntityTypeMatcher.matchEntityTypeEntryForLabel("Person"),
EntityTypeMatcher.matchEntityTypeEntryForLabel("Project"),
EntityTypeMatcher.matchEntityTypeEntryForLabel("OrgUnit"),
EntityTypeMatcher.matchEntityTypeEntryForLabel("Journal"),
EntityTypeMatcher.matchEntityTypeEntryForLabel("JournalVolume"),
EntityTypeMatcher.matchEntityTypeEntryForLabel("JournalIssue")
)))
;
}
@Test
public void findAllRelationshipTypesForPublications() throws Exception {
context.turnOffAuthorisationSystem();
EntityType publicationEntityType = entityTypeService.findByEntityType(context, "Publication");
EntityType personEntityType = entityTypeService.findByEntityType(context, "Person");
EntityType projectEntityType = entityTypeService.findByEntityType(context, "Project");
EntityType orgunitEntityType = entityTypeService.findByEntityType(context, "OrgUnit");
EntityType journalIssueEntityType = entityTypeService.findByEntityType(context, "journalIssue");
RelationshipType relationshipType1 = relationshipTypeService
.findbyTypesAndLabels(context, publicationEntityType, personEntityType, "isAuthorOfPublication",
"isPublicationOfAuthor");
RelationshipType relationshipType2 = relationshipTypeService
.findbyTypesAndLabels(context, publicationEntityType, projectEntityType, "isProjectOfPublication",
"isPublicationOfProject");
RelationshipType relationshipType3 = relationshipTypeService
.findbyTypesAndLabels(context, publicationEntityType, orgunitEntityType, "isOrgUnitOfPublication",
"isPublicationOfOrgUnit");
RelationshipType relationshipType4 = relationshipTypeService
.findbyTypesAndLabels(context, journalIssueEntityType, publicationEntityType, "isPublicationOfJournalIssue",
"isJournalIssueOfPublication");
RelationshipType relationshipType5 = relationshipTypeService
.findbyTypesAndLabels(context, publicationEntityType, orgunitEntityType, "isAuthorOfPublication",
"isPublicationOfAuthor");
getClient().perform(get("/api/core/entitytypes/" + publicationEntityType.getID() + "/relationshiptypes"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.relationshiptypes", containsInAnyOrder(
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipType1),
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipType2),
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipType3),
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipType4),
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipType5)
)));
}
@Test
public void createAndFindRelationships() throws Exception {
context.turnOffAuthorisationSystem();
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();
Collection col3 = CollectionBuilder.createCollection(context, child1).withName("OrgUnits").build();
Item author1 = ItemBuilder.createItem(context, col1)
.withTitle("Author1")
.withIssueDate("2017-10-17")
.withAuthor("Smith, Donald")
.withRelationshipType("Person")
.build();
Item author2 = ItemBuilder.createItem(context, col2)
.withTitle("Author2")
.withIssueDate("2016-02-13")
.withAuthor("Smith, Maria")
.withRelationshipType("Person")
.build();
Item author3 = ItemBuilder.createItem(context, col2)
.withTitle("Author3")
.withIssueDate("2016-02-13")
.withAuthor("Maybe, Maybe")
.withRelationshipType("Person")
.build();
Item orgUnit1 = ItemBuilder.createItem(context, col3)
.withTitle("OrgUnit1")
.withAuthor("Testy, TEst")
.withIssueDate("2015-01-01")
.withRelationshipType("OrgUnit")
.build();
Item project1 = ItemBuilder.createItem(context, col3)
.withTitle("Project1")
.withAuthor("Testy, TEst")
.withIssueDate("2015-01-01")
.withRelationshipType("Project")
.build();
Item publication = ItemBuilder.createItem(context, col3)
.withTitle("Publication1")
.withAuthor("Testy, TEst")
.withIssueDate("2015-01-01")
.withRelationshipType("Publication")
.build();
Item publication2 = ItemBuilder.createItem(context, col3)
.withTitle("Publication2")
.withIssueDate("2015-01-01")
.withRelationshipType("Publication")
.build();
RelationshipType isOrgUnitOfPersonRelationshipType = relationshipTypeService
.findbyTypesAndLabels(context, entityTypeService.findByEntityType(context, "Person"),
entityTypeService.findByEntityType(context, "OrgUnit"),
"isOrgUnitOfPerson", "isPersonOfOrgUnit");
RelationshipType isOrgUnitOfProjectRelationshipType = relationshipTypeService
.findbyTypesAndLabels(context, entityTypeService.findByEntityType(context, "Project"),
entityTypeService.findByEntityType(context, "OrgUnit"),
"isOrgUnitOfProject", "isProjectOfOrgUnit");
RelationshipType isAuthorOfPublicationRelationshipType = relationshipTypeService
.findbyTypesAndLabels(context, entityTypeService.findByEntityType(context, "Publication"),
entityTypeService.findByEntityType(context, "Person"),
"isAuthorOfPublication", "isPublicationOfAuthor");
Relationship relationship1 = RelationshipBuilder
.createRelationshipBuilder(context, publication, author1, isAuthorOfPublicationRelationshipType).build();
Relationship relationship2 = RelationshipBuilder
.createRelationshipBuilder(context, publication, author2, isAuthorOfPublicationRelationshipType).build();
Relationship relationship3 = RelationshipBuilder
.createRelationshipBuilder(context, publication2, author2, isAuthorOfPublicationRelationshipType).build();
Relationship relationship4 = RelationshipBuilder
.createRelationshipBuilder(context, publication2, author3, isAuthorOfPublicationRelationshipType).build();
getClient().perform(get("/api/core/relationships/isAuthorOfPublication"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder(
RelationshipMatcher.matchRelationship(relationship1),
RelationshipMatcher.matchRelationship(relationship2),
RelationshipMatcher.matchRelationship(relationship3),
RelationshipMatcher.matchRelationship(relationship4)
)));
getClient().perform(get("/api/core/relationships/isAuthorOfPublication?dso=" + publication.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder(
RelationshipMatcher.matchRelationship(relationship1),
RelationshipMatcher.matchRelationship(relationship2)
)));
getClient().perform(get("/api/core/relationships/isAuthorOfPublication?dso=" + publication2.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.relationships", containsInAnyOrder(
RelationshipMatcher.matchRelationship(relationship3),
RelationshipMatcher.matchRelationship(relationship4)
)));
}
}

View File

@@ -96,7 +96,7 @@ public class RelationshipTypeRestRepositoryIT extends AbstractControllerIntegrat
@Test
public void findAllRelationshipTypesTest() throws SQLException {
assertEquals(9, relationshipTypeService.findAll(context).size());
assertEquals(10, relationshipTypeService.findAll(context).size());
}
@Test
@@ -196,7 +196,7 @@ public class RelationshipTypeRestRepositoryIT extends AbstractControllerIntegrat
//We expect a 200 OK status
.andExpect(status().isOk())
//The type has to be 'discover'
.andExpect(jsonPath("$.page.totalElements", is(9)))
.andExpect(jsonPath("$.page.totalElements", is(10)))
//There needs to be a self link to this endpoint
.andExpect(jsonPath("$._links.self.href", containsString("api/core/relationshiptypes")))
//We have 4 facets in the default configuration, they need to all be present in the embedded section
@@ -209,7 +209,8 @@ public class RelationshipTypeRestRepositoryIT extends AbstractControllerIntegrat
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipTypes.get(5)),
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipTypes.get(6)),
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipTypes.get(7)),
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipTypes.get(8)))
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipTypes.get(8)),
RelationshipTypeMatcher.matchRelationshipTypeEntry(relationshipTypes.get(9)))
));
}