88056: Copy relationships when creating new version of item

This commit is contained in:
Bruno Roemers
2022-03-04 16:13:49 +01:00
parent b912769580
commit 272fd35535
3 changed files with 554 additions and 0 deletions

View File

@@ -15,7 +15,9 @@ import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.content.Item;
import org.dspace.content.Relationship;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Context;
import org.dspace.identifier.IdentifierException;
@@ -44,6 +46,8 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen
protected VersioningService versioningService;
@Autowired(required = true)
protected IdentifierService identifierService;
@Autowired(required = true)
protected RelationshipService relationshipService;
@Override
public Item createNewItemAndAddItInWorkspace(Context context, Item nativeItem) {
@@ -89,10 +93,18 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen
}
}
/**
* Copy all data (minus a few exceptions) from the old item to the new item.
* @param c the DSpace context.
* @param itemNew the new version of the item.
* @param previousItem the old version of the item.
* @return the new version of the item, with data from the old item.
*/
@Override
public Item updateItemState(Context c, Item itemNew, Item previousItem) {
try {
copyMetadata(c, itemNew, previousItem);
copyRelationships(c, itemNew, previousItem);
createBundlesAndAddBitstreams(c, itemNew, previousItem);
try {
identifierService.reserve(c, itemNew);
@@ -114,4 +126,49 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* Copy all relationships of the old item to the new item.
* At this point in the lifecycle of the item-version (before archival), only the opposite item receives
* "latest" status. On item archival of the item-version, the "latest" status of the relevant relationships
* will be updated.
* @param context the DSpace context.
* @param newItem the new version of the item.
* @param oldItem the old version of the item.
*/
protected void copyRelationships(
Context context, Item newItem, Item oldItem
) throws SQLException, AuthorizeException {
List<Relationship> oldRelationships = relationshipService.findByItem(context, oldItem, -1, -1, false, true);
for (Relationship oldRelationship : oldRelationships) {
if (oldRelationship.getLeftItem().equals(oldItem)) {
// current item is on left side of this relationship
relationshipService.create(
context,
newItem, // new item
oldRelationship.getRightItem(),
oldRelationship.getRelationshipType(),
oldRelationship.getLeftPlace(),
oldRelationship.getRightPlace(),
oldRelationship.getLeftwardValue(),
oldRelationship.getRightwardValue(),
Relationship.LatestVersionStatus.RIGHT_ONLY // only mark the opposite side as "latest" for now
);
} else if (oldRelationship.getRightItem().equals(oldItem)) {
// current item is on right side of this relationship
relationshipService.create(
context,
oldRelationship.getLeftItem(),
newItem, // new item
oldRelationship.getRelationshipType(),
oldRelationship.getLeftPlace(),
oldRelationship.getRightPlace(),
oldRelationship.getLeftwardValue(),
oldRelationship.getRightwardValue(),
Relationship.LatestVersionStatus.LEFT_ONLY // only mark the opposite side as "latest" for now
);
}
}
}
}

View File

@@ -22,5 +22,12 @@ public interface ItemVersionProvider {
public void deleteVersionedItem(Context c, Version versionToDelete, VersionHistory history) throws SQLException;
/**
* Copy all data (minus a few exceptions) from the old item to the new item.
* @param c the DSpace context.
* @param itemNew the new version of the item.
* @param previousItem the old version of the item.
* @return the new version of the item, with data from the old item.
*/
public Item updateItemState(Context c, Item itemNew, Item previousItem);
}

View File

@@ -0,0 +1,490 @@
/**
* 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.content;
import static org.dspace.content.Relationship.LatestVersionStatus;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertNotSame;
import java.util.List;
import org.dspace.AbstractIntegrationTestWithDatabase;
import org.dspace.builder.CollectionBuilder;
import org.dspace.builder.CommunityBuilder;
import org.dspace.builder.EntityTypeBuilder;
import org.dspace.builder.ItemBuilder;
import org.dspace.builder.RelationshipBuilder;
import org.dspace.builder.RelationshipTypeBuilder;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.RelationshipService;
import org.dspace.versioning.Version;
import org.dspace.versioning.factory.VersionServiceFactory;
import org.dspace.versioning.service.VersioningService;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
public class VersioningWithRelationshipsTest extends AbstractIntegrationTestWithDatabase {
private RelationshipService relationshipService;
private VersioningService versioningService;
protected Community community;
protected Collection collection;
protected EntityType publicationEntityType;
protected EntityType personEntityType;
protected EntityType projectEntityType;
protected EntityType orgUnitEntityType;
protected RelationshipType isAuthorOfPublication;
protected RelationshipType isProjectOfPublication;
protected RelationshipType isOrgUnitOfPublication;
protected RelationshipType isMemberOfProject;
protected RelationshipType isMemberOfOrgUnit;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
relationshipService = ContentServiceFactory.getInstance().getRelationshipService();
versioningService = VersionServiceFactory.getInstance().getVersionService();
context.turnOffAuthorisationSystem();
community = CommunityBuilder.createCommunity(context)
.withName("community")
.build();
collection = CollectionBuilder.createCollection(context, community)
.withName("collection")
.build();
publicationEntityType = EntityTypeBuilder.createEntityTypeBuilder(context, "Publication")
.build();
personEntityType = EntityTypeBuilder.createEntityTypeBuilder(context, "Person")
.build();
projectEntityType = EntityTypeBuilder.createEntityTypeBuilder(context, "Project")
.build();
orgUnitEntityType = EntityTypeBuilder.createEntityTypeBuilder(context, "OrgUnit")
.build();
isAuthorOfPublication = RelationshipTypeBuilder.createRelationshipTypeBuilder(
context, publicationEntityType, personEntityType,
"isAuthorOfPublication", "isPublicationOfAuthor",
null, null, null, null
)
.withCopyToLeft(false)
.withCopyToRight(false)
.build();
isProjectOfPublication = RelationshipTypeBuilder.createRelationshipTypeBuilder(
context, publicationEntityType, projectEntityType,
"isProjectOfPublication", "isPublicationOfProject",
0, null, 0, null
)
.withCopyToLeft(false)
.withCopyToRight(false)
.build();
isOrgUnitOfPublication = RelationshipTypeBuilder.createRelationshipTypeBuilder(
context, publicationEntityType, orgUnitEntityType,
"isOrgUnitOfPublication", "isPublicationOfOrgUnit",
0, null, 0, null
)
.withCopyToLeft(false)
.withCopyToRight(false)
.build();
isMemberOfProject = RelationshipTypeBuilder.createRelationshipTypeBuilder(
context, projectEntityType, personEntityType,
"isMemberOfProject", "isProjectOfMember",
null, null, null, null
)
.withCopyToLeft(false)
.withCopyToRight(false)
.build();
isMemberOfOrgUnit = RelationshipTypeBuilder.createRelationshipTypeBuilder(
context, orgUnitEntityType, personEntityType,
"isMemberOfOrgUnit", "isOrgUnitOfMember",
null, null, null, null
)
.withCopyToLeft(false)
.withCopyToRight(false)
.build();
}
protected Matcher<Object> isRelationship(
Item leftItem, RelationshipType relationshipType, Item rightItem, LatestVersionStatus latestVersionStatus
) {
return allOf(
hasProperty("leftItem", is(leftItem)),
hasProperty("relationshipType", is(relationshipType)),
hasProperty("rightItem", is(rightItem)),
// NOTE: place is not checked
hasProperty("leftwardValue", nullValue()),
hasProperty("rightwardValue", nullValue()),
hasProperty("latestVersionStatus", is(latestVersionStatus))
);
}
@Test
public void test_createNewVersionOfItemOnLeftSideOfRelationships() throws Exception {
///////////////////////////////////////////////
// create a publication with 3 relationships //
///////////////////////////////////////////////
Item person1 = ItemBuilder.createItem(context, collection)
.withTitle("person 1")
.withMetadata("dspace", "entity", "type", personEntityType.getLabel())
.build();
Item project1 = ItemBuilder.createItem(context, collection)
.withTitle("project 1")
.withMetadata("dspace", "entity", "type", projectEntityType.getLabel())
.build();
Item orgUnit1 = ItemBuilder.createItem(context, collection)
.withTitle("org unit 1")
.withMetadata("dspace", "entity", "type", orgUnitEntityType.getLabel())
.build();
Item originalPublication = ItemBuilder.createItem(context, collection)
.withTitle("original publication")
.withMetadata("dspace", "entity", "type", publicationEntityType.getLabel())
.build();
RelationshipBuilder.createRelationshipBuilder(context, originalPublication, person1, isAuthorOfPublication)
.build();
RelationshipBuilder.createRelationshipBuilder(context, originalPublication, project1, isProjectOfPublication)
.build();
RelationshipBuilder.createRelationshipBuilder(context, originalPublication, orgUnit1, isOrgUnitOfPublication)
.build();
/////////////////////////////////////////////////////////
// verify that the relationships were properly created //
/////////////////////////////////////////////////////////
assertThat(
relationshipService.findByItem(context, originalPublication, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isAuthorOfPublication, person1, LatestVersionStatus.BOTH),
isRelationship(originalPublication, isProjectOfPublication, project1, LatestVersionStatus.BOTH),
isRelationship(originalPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, person1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isAuthorOfPublication, person1, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, project1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isProjectOfPublication, project1, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, orgUnit1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.BOTH)
))
);
/////////////////////////////////////////////
// create a new version of the publication //
/////////////////////////////////////////////
Version newVersion = versioningService.createNewVersion(context, originalPublication);
Item newPublication = newVersion.getItem();
assertNotSame(originalPublication, newPublication);
///////////////////////////////////////////////////////////////////////
// verify the relationships of all 5 items (excludeNonLatest = true) //
///////////////////////////////////////////////////////////////////////
assertThat(
relationshipService.findByItem(context, originalPublication, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isAuthorOfPublication, person1, LatestVersionStatus.BOTH),
isRelationship(originalPublication, isProjectOfPublication, project1, LatestVersionStatus.BOTH),
isRelationship(originalPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, person1, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isAuthorOfPublication, person1, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, project1, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isProjectOfPublication, project1, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, orgUnit1, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, newPublication, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(newPublication, isAuthorOfPublication, person1, LatestVersionStatus.RIGHT_ONLY),
isRelationship(newPublication, isProjectOfPublication, project1, LatestVersionStatus.RIGHT_ONLY),
isRelationship(newPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.RIGHT_ONLY)
))
);
////////////////////////////////////////////////////////////////////////
// verify the relationships of all 5 items (excludeNonLatest = false) //
////////////////////////////////////////////////////////////////////////
assertThat(
relationshipService.findByItem(context, originalPublication, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isAuthorOfPublication, person1, LatestVersionStatus.BOTH),
isRelationship(originalPublication, isProjectOfPublication, project1, LatestVersionStatus.BOTH),
isRelationship(originalPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, person1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isAuthorOfPublication, person1, LatestVersionStatus.BOTH),
isRelationship(newPublication, isAuthorOfPublication, person1, LatestVersionStatus.RIGHT_ONLY)
))
);
assertThat(
relationshipService.findByItem(context, project1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isProjectOfPublication, project1, LatestVersionStatus.BOTH),
isRelationship(newPublication, isProjectOfPublication, project1, LatestVersionStatus.RIGHT_ONLY)
))
);
assertThat(
relationshipService.findByItem(context, orgUnit1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(originalPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.BOTH),
isRelationship(newPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.RIGHT_ONLY)
))
);
assertThat(
relationshipService.findByItem(context, newPublication, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(newPublication, isAuthorOfPublication, person1, LatestVersionStatus.RIGHT_ONLY),
isRelationship(newPublication, isProjectOfPublication, project1, LatestVersionStatus.RIGHT_ONLY),
isRelationship(newPublication, isOrgUnitOfPublication, orgUnit1, LatestVersionStatus.RIGHT_ONLY)
))
);
//////////////
// clean up //
//////////////
versioningService.removeVersion(context, newPublication);
}
@Test
public void test_createNewVersionOfItemOnRightSideOfRelationships() throws Exception {
///////////////////////////////////////////////
// create a publication with 3 relationships //
///////////////////////////////////////////////
Item publication1 = ItemBuilder.createItem(context, collection)
.withTitle("publication 1")
.withMetadata("dspace", "entity", "type", publicationEntityType.getLabel())
.build();
Item project1 = ItemBuilder.createItem(context, collection)
.withTitle("project 1")
.withMetadata("dspace", "entity", "type", projectEntityType.getLabel())
.build();
Item orgUnit1 = ItemBuilder.createItem(context, collection)
.withTitle("org unit 1")
.withMetadata("dspace", "entity", "type", orgUnitEntityType.getLabel())
.build();
Item originalPerson = ItemBuilder.createItem(context, collection)
.withTitle("original person")
.withMetadata("dspace", "entity", "type", personEntityType.getLabel())
.build();
RelationshipBuilder.createRelationshipBuilder(context, publication1, originalPerson, isAuthorOfPublication)
.build();
RelationshipBuilder.createRelationshipBuilder(context, project1, originalPerson, isMemberOfProject)
.build();
RelationshipBuilder.createRelationshipBuilder(context, orgUnit1, originalPerson, isMemberOfOrgUnit)
.build();
/////////////////////////////////////////////////////////
// verify that the relationships were properly created //
/////////////////////////////////////////////////////////
assertThat(
relationshipService.findByItem(context, originalPerson, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(publication1, isAuthorOfPublication, originalPerson, LatestVersionStatus.BOTH),
isRelationship(project1, isMemberOfProject, originalPerson, LatestVersionStatus.BOTH),
isRelationship(orgUnit1, isMemberOfOrgUnit, originalPerson, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, publication1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(publication1, isAuthorOfPublication, originalPerson, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, project1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(project1, isMemberOfProject, originalPerson, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, orgUnit1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(orgUnit1, isMemberOfOrgUnit, originalPerson, LatestVersionStatus.BOTH)
))
);
////////////////////////////////////////
// create a new version of the person //
////////////////////////////////////////
Version newVersion = versioningService.createNewVersion(context, originalPerson);
Item newPerson = newVersion.getItem();
assertNotSame(originalPerson, newPerson);
///////////////////////////////////////////////////////////////////////
// verify the relationships of all 5 items (excludeNonLatest = true) //
///////////////////////////////////////////////////////////////////////
assertThat(
relationshipService.findByItem(context, originalPerson, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(publication1, isAuthorOfPublication, originalPerson, LatestVersionStatus.BOTH),
isRelationship(project1, isMemberOfProject, originalPerson, LatestVersionStatus.BOTH),
isRelationship(orgUnit1, isMemberOfOrgUnit, originalPerson, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, publication1, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(publication1, isAuthorOfPublication, originalPerson, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, project1, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(project1, isMemberOfProject, originalPerson, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, orgUnit1, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(orgUnit1, isMemberOfOrgUnit, originalPerson, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, newPerson, -1, -1, false, true),
containsInAnyOrder(List.of(
isRelationship(publication1, isAuthorOfPublication, newPerson, LatestVersionStatus.LEFT_ONLY),
isRelationship(project1, isMemberOfProject, newPerson, LatestVersionStatus.LEFT_ONLY),
isRelationship(orgUnit1, isMemberOfOrgUnit, newPerson, LatestVersionStatus.LEFT_ONLY)
))
);
////////////////////////////////////////////////////////////////////////
// verify the relationships of all 5 items (excludeNonLatest = false) //
////////////////////////////////////////////////////////////////////////
assertThat(
relationshipService.findByItem(context, originalPerson, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(publication1, isAuthorOfPublication, originalPerson, LatestVersionStatus.BOTH),
isRelationship(project1, isMemberOfProject, originalPerson, LatestVersionStatus.BOTH),
isRelationship(orgUnit1, isMemberOfOrgUnit, originalPerson, LatestVersionStatus.BOTH)
))
);
assertThat(
relationshipService.findByItem(context, publication1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(publication1, isAuthorOfPublication, originalPerson, LatestVersionStatus.BOTH),
isRelationship(publication1, isAuthorOfPublication, newPerson, LatestVersionStatus.LEFT_ONLY)
))
);
assertThat(
relationshipService.findByItem(context, project1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(project1, isMemberOfProject, originalPerson, LatestVersionStatus.BOTH),
isRelationship(project1, isMemberOfProject, newPerson, LatestVersionStatus.LEFT_ONLY)
))
);
assertThat(
relationshipService.findByItem(context, orgUnit1, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(orgUnit1, isMemberOfOrgUnit, originalPerson, LatestVersionStatus.BOTH),
isRelationship(orgUnit1, isMemberOfOrgUnit, newPerson, LatestVersionStatus.LEFT_ONLY)
))
);
assertThat(
relationshipService.findByItem(context, newPerson, -1, -1, false, false),
containsInAnyOrder(List.of(
isRelationship(publication1, isAuthorOfPublication, newPerson, LatestVersionStatus.LEFT_ONLY),
isRelationship(project1, isMemberOfProject, newPerson, LatestVersionStatus.LEFT_ONLY),
isRelationship(orgUnit1, isMemberOfOrgUnit, newPerson, LatestVersionStatus.LEFT_ONLY)
))
);
//////////////
// clean up //
//////////////
versioningService.removeVersion(context, newPerson);
}
}