Merge remote-tracking branch 'dspace/master' into w2p-65247_Create-Read-on-Collection-and-Community-logo

This commit is contained in:
Peter Nijs
2019-10-25 13:45:32 +02:00
151 changed files with 7186 additions and 2195 deletions

View File

@@ -3,4 +3,9 @@
.settings/ .settings/
*/target/ */target/
dspace/modules/*/target/ dspace/modules/*/target/
Dockerfile.* Dockerfile.*
dspace/src/main/docker/dspace-postgres-pgcrypto
dspace/src/main/docker/dspace-postgres-pgcrypto-curl
dspace/src/main/docker/solr
dspace/src/main/docker/README.md
dspace/src/main/docker-compose/

View File

@@ -3,12 +3,12 @@
[![Build Status](https://travis-ci.org/DSpace/DSpace.png?branch=master)](https://travis-ci.org/DSpace/DSpace) [![Build Status](https://travis-ci.org/DSpace/DSpace.png?branch=master)](https://travis-ci.org/DSpace/DSpace)
[DSpace Documentation](https://wiki.duraspace.org/display/DSDOC/) | [DSpace Documentation](https://wiki.duraspace.org/display/DSDOC/) |
[DSpace Releases](https://github.com/DSpace/DSpace/releases) | [DSpace Releases](https://github.com/DSpace/DSpace/releases) |
[DSpace Wiki](https://wiki.duraspace.org/display/DSPACE/Home) | [DSpace Wiki](https://wiki.duraspace.org/display/DSPACE/Home) |
[Support](https://wiki.duraspace.org/display/DSPACE/Support) [Support](https://wiki.duraspace.org/display/DSPACE/Support)
DSpace open source software is a turnkey repository application used by more than DSpace open source software is a turnkey repository application used by more than
2,000 organizations and institutions worldwide to provide durable access to digital resources. 2,000 organizations and institutions worldwide to provide durable access to digital resources.
For more information, visit http://www.dspace.org/ For more information, visit http://www.dspace.org/
@@ -17,7 +17,7 @@ For more information, visit http://www.dspace.org/
* DSpace 7 REST API work is occurring on the [`master` branch](https://github.com/DSpace/DSpace/tree/master/dspace-server-webapp) of this repository. * DSpace 7 REST API work is occurring on the [`master` branch](https://github.com/DSpace/DSpace/tree/master/dspace-server-webapp) of this repository.
* The REST Contract is being documented at https://github.com/DSpace/Rest7Contract * The REST Contract is being documented at https://github.com/DSpace/Rest7Contract
* DSpace 7 Angular UI work is occurring at https://github.com/DSpace/dspace-angular * DSpace 7 Angular UI work is occurring at https://github.com/DSpace/dspace-angular
**If you would like to get involved in our DSpace 7 development effort, we welcome new contributors.** Just join one of our meetings or get in touch via Slack. See the [DSpace 7 UI Working Group](https://wiki.duraspace.org/display/DSPACE/DSpace+7+UI+Working+Group) wiki page for more info. **If you would like to get involved in our DSpace 7 development effort, we welcome new contributors.** Just join one of our meetings or get in touch via Slack. See the [DSpace 7 UI Working Group](https://wiki.duraspace.org/display/DSPACE/DSpace+7+UI+Working+Group) wiki page for more info.
**If you are looking for the ongoing maintenance work for DSpace 6 (or prior releases)**, you can find that work on the corresponding maintenance branch (e.g. [`dspace-6_x`](https://github.com/DSpace/DSpace/tree/dspace-6_x)) in this repository. **If you are looking for the ongoing maintenance work for DSpace 6 (or prior releases)**, you can find that work on the corresponding maintenance branch (e.g. [`dspace-6_x`](https://github.com/DSpace/DSpace/tree/dspace-6_x)) in this repository.
@@ -31,21 +31,21 @@ Past releases are all available via GitHub at https://github.com/DSpace/DSpace/r
## Documentation / Installation ## Documentation / Installation
Documentation for each release may be viewed online or downloaded via our [Documentation Wiki](https://wiki.duraspace.org/display/DSDOC/). Documentation for each release may be viewed online or downloaded via our [Documentation Wiki](https://wiki.duraspace.org/display/DSDOC/).
The latest DSpace Installation instructions are available at: The latest DSpace Installation instructions are available at:
https://wiki.duraspace.org/display/DSDOC6x/Installing+DSpace https://wiki.duraspace.org/display/DSDOC6x/Installing+DSpace
Please be aware that, as a Java web application, DSpace requires a database (PostgreSQL or Oracle) Please be aware that, as a Java web application, DSpace requires a database (PostgreSQL or Oracle)
and a servlet container (usually Tomcat) in order to function. and a servlet container (usually Tomcat) in order to function.
More information about these and all other prerequisites can be found in the Installation instructions above. More information about these and all other prerequisites can be found in the Installation instructions above.
## Dockerfile Usage ## Running DSpace 7 in Docker
See the [DSpace Docker Tutorial](https://dspace-labs.github.io/DSpace-Docker-Images/). See [Running DSpace 7 with Docker Compose](dspace/src/main/docker-compose/README.md)
## Contributing ## Contributing
DSpace is a community built and supported project. We do not have a centralized development or support team, DSpace is a community built and supported project. We do not have a centralized development or support team,
but have a dedicated group of volunteers who help us improve the software, documentation, resources, etc. but have a dedicated group of volunteers who help us improve the software, documentation, resources, etc.
We welcome contributions of any type. Here's a few basic guides that provide suggestions for contributing to DSpace: We welcome contributions of any type. Here's a few basic guides that provide suggestions for contributing to DSpace:
@@ -71,8 +71,8 @@ Great Q&A is also available under the [DSpace tag on Stackoverflow](http://stack
Additional support options are listed at https://wiki.duraspace.org/display/DSPACE/Support Additional support options are listed at https://wiki.duraspace.org/display/DSPACE/Support
DSpace also has an active service provider network. If you'd rather hire a service provider to DSpace also has an active service provider network. If you'd rather hire a service provider to
install, upgrade, customize or host DSpace, then we recommend getting in touch with one of our install, upgrade, customize or host DSpace, then we recommend getting in touch with one of our
[Registered Service Providers](http://www.dspace.org/service-providers). [Registered Service Providers](http://www.dspace.org/service-providers).
## Issue Tracker ## Issue Tracker
@@ -101,7 +101,7 @@ run automatically by [Travis CI](https://travis-ci.org/DSpace/DSpace/) for all P
# Run all tests in a specific test class # Run all tests in a specific test class
# NOTE: testClassName is just the class name, do not include package # NOTE: testClassName is just the class name, do not include package
mvn clean test -Dmaven.test.skip=false -Dtest=[testClassName] mvn clean test -Dmaven.test.skip=false -Dtest=[testClassName]
# Run one test method in a specific test class # Run one test method in a specific test class
mvn clean test -Dmaven.test.skip=false -Dtest=[testClassName]#[testMethodName] mvn clean test -Dmaven.test.skip=false -Dtest=[testClassName]#[testMethodName]
``` ```
@@ -115,7 +115,7 @@ run automatically by [Travis CI](https://travis-ci.org/DSpace/DSpace/) for all P
# NOTE: Integration Tests only run for "verify" or "install" phases # NOTE: Integration Tests only run for "verify" or "install" phases
# NOTE: testClassName is just the class name, do not include package # NOTE: testClassName is just the class name, do not include package
mvn clean verify -Dmaven.test.skip=false -DskipITs=false -Dit.test=[testClassName] mvn clean verify -Dmaven.test.skip=false -DskipITs=false -Dit.test=[testClassName]
# Run one test method in a specific test class # Run one test method in a specific test class
mvn clean verify -Dmaven.test.skip=false -DskipITs=false -Dit.test=[testClassName]#[testMethodName] mvn clean verify -Dmaven.test.skip=false -DskipITs=false -Dit.test=[testClassName]#[testMethodName]
``` ```
@@ -124,7 +124,7 @@ run automatically by [Travis CI](https://travis-ci.org/DSpace/DSpace/) for all P
# Before you can run only one module's tests, other modules may need installing into your ~/.m2 # Before you can run only one module's tests, other modules may need installing into your ~/.m2
cd [dspace-src] cd [dspace-src]
mvn clean install mvn clean install
# Then, move into a module subdirectory, and run the test command # Then, move into a module subdirectory, and run the test command
cd [dspace-src]/dspace-server-webapp cd [dspace-src]/dspace-server-webapp
# Choose your test command from the lists above # Choose your test command from the lists above

25
docker-compose-cli.yml Normal file
View File

@@ -0,0 +1,25 @@
version: "3.7"
services:
dspace-cli:
image: "${DOCKER_OWNER:-dspace}/dspace-cli:${DSPACE_VER:-dspace-7_x}"
container_name: dspace-cli
build:
context: .
dockerfile: Dockerfile.cli.jdk8
#environment:
volumes:
- ./dspace/src/main/docker-compose/local.cfg:/dspace/config/local.cfg
- assetstore:/dspace/assetstore
entrypoint: /dspace/bin/dspace
command: help
networks:
- dspacenet
tty: true
stdin_open: true
volumes:
assetstore:
networks:
dspacenet:

62
docker-compose.yml Normal file
View File

@@ -0,0 +1,62 @@
version: '3.7'
networks:
dspacenet:
services:
dspace:
container_name: dspace
image: "${DOCKER_OWNER:-dspace}/dspace:${DSPACE_VER:-dspace-7_x-jdk8-test}"
build:
context: .
dockerfile: Dockerfile.jdk8-test
depends_on:
- dspacedb
networks:
dspacenet:
ports:
- published: 8080
target: 8080
stdin_open: true
tty: true
volumes:
- assetstore:/dspace/assetstore
- ./dspace/src/main/docker-compose/local.cfg:/dspace/config/local.cfg
# Ensure that the database is ready before starting tomcat
entrypoint:
- /bin/bash
- '-c'
- |
/dspace/bin/dspace database migrate
catalina.sh run
dspacedb:
container_name: dspacedb
environment:
PGDATA: /pgdata
image: dspace/dspace-postgres-pgcrypto
networks:
dspacenet:
stdin_open: true
tty: true
volumes:
- pgdata:/pgdata
dspacesolr:
container_name: dspacesolr
image: dspace/dspace-solr
networks:
dspacenet:
ports:
- published: 8983
target: 8983
stdin_open: true
tty: true
volumes:
- solr_authority:/opt/solr/server/solr/authority/data
- solr_oai:/opt/solr/server/solr/oai/data
- solr_search:/opt/solr/server/solr/search/data
- solr_statistics:/opt/solr/server/solr/statistics/data
volumes:
assetstore:
pgdata:
solr_authority:
solr_oai:
solr_search:
solr_statistics:

View File

@@ -17,8 +17,8 @@ import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -38,7 +38,6 @@ import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Entity; import org.dspace.content.Entity;
import org.dspace.content.EntityType;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataSchemaEnum;
@@ -106,19 +105,44 @@ public class MetadataImport {
protected static final String AC_PREFIX = "authority.controlled."; protected static final String AC_PREFIX = "authority.controlled.";
/** /**
* Map of field:value to csv row number, used to resolve indirect entity references. * Map of field:value to csv row number, used to resolve indirect entity target references.
* *
* @see #populateRefAndRowMap(DSpaceCSVLine, int, UUID) * @see #populateRefAndRowMap(DSpaceCSVLine, UUID)
*/ */
protected HashMap<String, Set<Integer>> csvRefMap = new HashMap<>(); protected Map<String, Set<Integer>> csvRefMap = new HashMap<>();
/** /**
* Map of csv row number to UUID, used to resolve indirect entity references. * Map of csv row number to UUID, used to resolve indirect entity target references.
* *
* @see #populateRefAndRowMap(DSpaceCSVLine, int, UUID) * @see #populateRefAndRowMap(DSpaceCSVLine, UUID)
*/ */
protected HashMap<Integer, UUID> csvRowMap = new HashMap<>(); protected HashMap<Integer, UUID> csvRowMap = new HashMap<>();
/**
* Map of UUIDs to their entity types.
*
* @see #populateRefAndRowMap(DSpaceCSVLine, UUID)
*/
protected static HashMap<UUID, String> entityTypeMap = new HashMap<>();
/**
* Map of UUIDs to their relations that are referenced within any import with their referers.
*
* @see #populateEntityRelationMap(String, String, String)
*/
protected static HashMap<String, HashMap<String, ArrayList<String>>> entityRelationMap = new HashMap<>();
/**
* Collection of errors generated during relation validation process.
*/
protected ArrayList<String> relationValidationErrors = new ArrayList<>();
/**
* Counter of rows proccssed in a CSV.
*/
protected Integer rowCount = 1;
/** /**
* Logger * Logger
*/ */
@@ -184,10 +208,10 @@ public class MetadataImport {
c.setMode(Context.Mode.BATCH_EDIT); c.setMode(Context.Mode.BATCH_EDIT);
// Process each change // Process each change
int rowCount = 1; rowCount = 1;
for (DSpaceCSVLine line : toImport) { for (DSpaceCSVLine line : toImport) {
//Resolve references to other items // Resolve target references to other items
populateRefAndRowMap(line, rowCount, null); populateRefAndRowMap(line, line.getID());
line = resolveEntityRefs(line); line = resolveEntityRefs(line);
// Get the DSpace item to compare with // Get the DSpace item to compare with
UUID id = line.getID(); UUID id = line.getID();
@@ -201,7 +225,7 @@ public class MetadataImport {
WorkflowItem wfItem = null; WorkflowItem wfItem = null;
Item item = null; Item item = null;
// Is this a new item? // Is this an existing item?
if (id != null) { if (id != null) {
// Get the item // Get the item
item = itemService.find(c, id); item = itemService.find(c, id);
@@ -238,9 +262,8 @@ public class MetadataImport {
} }
} }
} }
// Compare // Compare
compare(item, fromCSV, change, md, whatHasChanged, line); compareAndUpdate(item, fromCSV, change, md, whatHasChanged, line);
} }
} }
@@ -378,30 +401,23 @@ public class MetadataImport {
item = wsItem.getItem(); item = wsItem.getItem();
// Add the metadata to the item // Add the metadata to the item
List<BulkEditMetadataValue> relationships = new LinkedList<>(); for (BulkEditMetadataValue dcv : whatHasChanged.getAdds()) {
itemService.addMetadata(c, item, dcv.getSchema(),
dcv.getElement(),
dcv.getQualifier(),
dcv.getLanguage(),
dcv.getValue(),
dcv.getAuthority(),
dcv.getConfidence());
}
//Add relations after all metadata has been processed
for (BulkEditMetadataValue dcv : whatHasChanged.getAdds()) { for (BulkEditMetadataValue dcv : whatHasChanged.getAdds()) {
if (StringUtils.equals(dcv.getSchema(), MetadataSchemaEnum.RELATION.getName())) { if (StringUtils.equals(dcv.getSchema(), MetadataSchemaEnum.RELATION.getName())) {
addRelationship(c, item, dcv.getElement(), dcv.getValue());
if (!StringUtils.equals(dcv.getElement(), "type")) {
relationships.add(dcv);
} else {
handleRelationshipMetadataValueFromBulkEditMetadataValue(item, dcv);
}
} else {
itemService.addMetadata(c, item, dcv.getSchema(),
dcv.getElement(),
dcv.getQualifier(),
dcv.getLanguage(),
dcv.getValue(),
dcv.getAuthority(),
dcv.getConfidence());
} }
} }
for (BulkEditMetadataValue relationship : relationships) {
handleRelationshipMetadataValueFromBulkEditMetadataValue(item, relationship);
}
// Should the workflow be used? // Should the workflow be used?
if (useWorkflow) { if (useWorkflow) {
WorkflowService workflowService = WorkflowServiceFactory.getInstance().getWorkflowService(); WorkflowService workflowService = WorkflowServiceFactory.getInstance().getWorkflowService();
@@ -424,8 +440,6 @@ public class MetadataImport {
} }
} }
// Commit changes to the object
// c.commit();
whatHasChanged.setItem(item); whatHasChanged.setItem(item);
} }
@@ -439,7 +453,7 @@ public class MetadataImport {
c.uncacheEntity(wfItem); c.uncacheEntity(wfItem);
c.uncacheEntity(item); c.uncacheEntity(item);
} }
populateRefAndRowMap(line, rowCount, item == null ? null : item.getID()); populateRefAndRowMap(line, item == null ? null : item.getID());
// keep track of current rows processed // keep track of current rows processed
rowCount++; rowCount++;
} }
@@ -452,32 +466,14 @@ public class MetadataImport {
} }
// Return the changes // Return the changes
if (!change ) {
validateExpressedRelations();
}
return changes; return changes;
} }
/** /**
* This metod handles the BulkEditMetadataValue objects that correspond to Relationship metadatavalues * Compare an item metadata with a line from CSV, and optionally update the item.
* @param item The item to which this metadatavalue will belong
* @param dcv The BulkEditMetadataValue to be processed
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
private void handleRelationshipMetadataValueFromBulkEditMetadataValue(Item item, BulkEditMetadataValue dcv)
throws SQLException, AuthorizeException, MetadataImportException {
LinkedList<String> values = new LinkedList<>();
values.add(dcv.getValue());
LinkedList<String> authorities = new LinkedList<>();
authorities.add(dcv.getAuthority());
LinkedList<Integer> confidences = new LinkedList<>();
confidences.add(dcv.getConfidence());
handleRelationMetadata(c, item, dcv.getSchema(), dcv.getElement(),
dcv.getQualifier(),
dcv.getLanguage(), values, authorities, confidences);
}
/**
* Compare an item metadata with a line from CSV, and optionally update the item
* *
* @param item The current item metadata * @param item The current item metadata
* @param fromCSV The metadata from the CSV file * @param fromCSV The metadata from the CSV file
@@ -487,9 +483,10 @@ public class MetadataImport {
* @param line line in CSV file * @param line line in CSV file
* @throws SQLException if there is a problem accessing a Collection from the database, from its handle * @throws SQLException if there is a problem accessing a Collection from the database, from its handle
* @throws AuthorizeException if there is an authorization problem with permissions * @throws AuthorizeException if there is an authorization problem with permissions
* @throws MetadataImportException custom exception for error handling within metadataimport
*/ */
protected void compare(Item item, String[] fromCSV, boolean change, protected void compareAndUpdate(Item item, String[] fromCSV, boolean change,
String md, BulkEditChange changes, DSpaceCSVLine line) String md, BulkEditChange changes, DSpaceCSVLine line)
throws SQLException, AuthorizeException, MetadataImportException { throws SQLException, AuthorizeException, MetadataImportException {
// Log what metadata element we're looking at // Log what metadata element we're looking at
String all = ""; String all = "";
@@ -663,10 +660,9 @@ public class MetadataImport {
} }
} }
if (StringUtils.equals(schema, MetadataSchemaEnum.RELATION.getName())) { if (StringUtils.equals(schema, MetadataSchemaEnum.RELATION.getName())) {
List<RelationshipType> relationshipTypeList = relationshipTypeService List<RelationshipType> relationshipTypeList = relationshipTypeService
.findByLeftOrRightLabel(c, element); .findByLeftwardOrRightwardTypeName(c, element);
for (RelationshipType relationshipType : relationshipTypeList) { for (RelationshipType relationshipType : relationshipTypeList) {
for (Relationship relationship : relationshipService for (Relationship relationship : relationshipService
.findByItemAndRelationshipType(c, item, relationshipType)) { .findByItemAndRelationshipType(c, item, relationshipType)) {
@@ -674,7 +670,7 @@ public class MetadataImport {
relationshipService.update(c, relationship); relationshipService.update(c, relationship);
} }
} }
handleRelationMetadata(c, item, schema, element, qualifier, language, values, authorities, confidences); addRelationships(c, item, element, values);
} else { } else {
itemService.clearMetadata(c, item, schema, element, qualifier, language); itemService.clearMetadata(c, item, schema, element, qualifier, language);
itemService.addMetadata(c, item, schema, element, qualifier, itemService.addMetadata(c, item, schema, element, qualifier,
@@ -685,47 +681,35 @@ public class MetadataImport {
} }
/** /**
* This method decides whether the metadatavalue is of type relation.type or if it corresponds to *
* a relationship and handles it accordingly to their respective methods * Adds multiple relationships with a matching typeName to an item.
*
* @param c The relevant DSpace context * @param c The relevant DSpace context
* @param item The item to which this metadatavalue belongs to * @param item The item to which this metadatavalue belongs to
* @param schema The schema for the metadatavalue * @param typeName The element for the metadatavalue
* @param element The element for the metadatavalue * @param values to iterate over
* @param qualifier The qualifier for the metadatavalue
* @param language The language for the metadatavalue
* @param values The values for the metadatavalue
* @param authorities The authorities for the metadatavalue
* @param confidences The confidences for the metadatavalue
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong * @throws AuthorizeException If something goes wrong
*/ */
private void handleRelationMetadata(Context c, Item item, String schema, String element, String qualifier, private void addRelationships(Context c, Item item, String typeName, List<String> values)
String language, List<String> values, List<String> authorities, throws SQLException, AuthorizeException,
List<Integer> confidences) throws SQLException, AuthorizeException,
MetadataImportException { MetadataImportException {
for (String value : values) {
if (StringUtils.equals(element, "type") && StringUtils.isBlank(qualifier)) { addRelationship(c, item, typeName, value);
handleRelationTypeMetadata(c, item, schema, element, qualifier, language, values, authorities, confidences);
} else {
for (String value : values) {
handleRelationOtherMetadata(c, item, element, value);
}
} }
} }
/** /**
* Gets an existing entity from a reference. * Gets an existing entity from a target reference.
* *
* @param context the context to use. * @param context the context to use.
* @param reference the reference which may be a UUID, metadata reference, or rowName reference. * @param targetReference the target reference which may be a UUID, metadata reference, or rowName reference.
* @return the entity, which is guaranteed to exist. * @return the entity, which is guaranteed to exist.
* @throws MetadataImportException if the reference is badly formed or refers to a non-existing item. * @throws MetadataImportException if the target reference is badly formed or refers to a non-existing item.
*/ */
private Entity getEntity(Context context, String reference) throws MetadataImportException { private Entity getEntity(Context context, String targetReference) throws MetadataImportException {
Entity entity = null; Entity entity = null;
UUID uuid = resolveEntityRef(context, reference); UUID uuid = resolveEntityRef(context, targetReference);
// At this point, we have a uuid, so we can get an entity // At this point, we have a uuid, so we can get an entity
try { try {
entity = entityService.findByItemId(context, uuid); entity = entityService.findByItemId(context, uuid);
@@ -734,205 +718,73 @@ public class MetadataImport {
} }
return entity; return entity;
} catch (SQLException sqle) { } catch (SQLException sqle) {
throw new MetadataImportException("Unable to find entity using reference: " + reference, sqle); throw new MetadataImportException("Unable to find entity using reference: " + targetReference, sqle);
} }
} }
/** /**
* This method takes the item, element and values to determine what relationships should be built *
* for these parameters and calls on the method to construct them * Creates a relationship for the given item
*
* @param c The relevant DSpace context * @param c The relevant DSpace context
* @param item The item that the relationships will be made for * @param item The item that the relationships will be made for
* @param element The string determining which relationshiptype is to be used * @param typeName The relationship typeName
* @param value The value for the relationship * @param value The value for the relationship
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong * @throws AuthorizeException If something goes wrong
*/ */
private void handleRelationOtherMetadata(Context c, Item item, String element, String value) private void addRelationship(Context c, Item item, String typeName, String value)
throws SQLException, AuthorizeException, MetadataImportException { throws SQLException, AuthorizeException, MetadataImportException {
if (value.isEmpty()) { if (value.isEmpty()) {
return; return;
} }
Entity entity = entityService.findByItemId(c, item.getID());
boolean left = false; boolean left = false;
List<RelationshipType> acceptableRelationshipTypes = new LinkedList<>();
// Get entity from target reference
Entity relationEntity = getEntity(c, value); Entity relationEntity = getEntity(c, value);
// Get relationship type of entity and item
String relationEntityRelationshipType = itemService.getMetadata(relationEntity.getItem(),
"relationship", "type",
null, Item.ANY).get(0).getValue();
String itemRelationshipType = itemService.getMetadata(item, "relationship", "type",
null, Item.ANY).get(0).getValue();
List<RelationshipType> leftRelationshipTypesForEntity = entityService.getLeftRelationshipTypes(c, entity); // Get the correct RelationshipType based on typeName
List<RelationshipType> rightRelationshipTypesForEntity = entityService.getRightRelationshipTypes(c, entity); List<RelationshipType> relType = relationshipTypeService.findByLeftwardOrRightwardTypeName(c, typeName);
RelationshipType foundRelationshipType = matchRelationshipType(relType,
relationEntityRelationshipType, itemRelationshipType, typeName);
for (RelationshipType relationshipType : entityService.getAllRelationshipTypes(c, entity)) { if (foundRelationshipType == null) {
if (StringUtils.equalsIgnoreCase(relationshipType.getLeftLabel(), element)) { throw new MetadataImportException("Error on CSV row " + rowCount + ":" + "\n" +
left = handleLeftLabelEqualityRelationshipTypeElement(c, entity, relationEntity, left, "No Relationship type found for:\n" +
acceptableRelationshipTypes, "Target type: " + relationEntityRelationshipType + "\n" +
leftRelationshipTypesForEntity, "Origin referer type: " + itemRelationshipType + "\n" +
relationshipType); "with typeName: " + typeName);
} else if (StringUtils.equalsIgnoreCase(relationshipType.getRightLabel(), element)) {
left = handleRightLabelEqualityRelationshipTypeElement(c, entity, relationEntity, left,
acceptableRelationshipTypes,
rightRelationshipTypesForEntity,
relationshipType);
}
} }
if (acceptableRelationshipTypes.size() > 1) { if (foundRelationshipType.getLeftwardType().equalsIgnoreCase(typeName)) {
log.error("Ambiguous relationship_types were found"); left = true;
return;
}
if (acceptableRelationshipTypes.size() == 0) {
log.error("no relationship_types were found");
return;
} }
//There is exactly one // Placeholder items for relation placing
buildRelationObject(c, item, relationEntity.getItem(), left, acceptableRelationshipTypes.get(0));
}
/**
* This method creates the relationship for the item and stores it in the database
* @param c The relevant DSpace context
* @param item The item for which this relationship will be constructed
* @param otherItem The item for the relationship
* @param left A boolean indicating whether the item is the leftItem or the rightItem
* @param acceptedRelationshipType The acceptable relationship type
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
private void buildRelationObject(Context c, Item item, Item otherItem, boolean left,
RelationshipType acceptedRelationshipType)
throws SQLException, AuthorizeException {
Item leftItem = null; Item leftItem = null;
Item rightItem = null; Item rightItem = null;
if (left) { if (left) {
leftItem = item; leftItem = item;
rightItem = otherItem; rightItem = relationEntity.getItem();
} else { } else {
leftItem = relationEntity.getItem();
rightItem = item; rightItem = item;
leftItem = otherItem;
} }
RelationshipType relationshipType = acceptedRelationshipType;
// Create the relationship
int leftPlace = relationshipService.findLeftPlaceByLeftItem(c, leftItem) + 1; int leftPlace = relationshipService.findLeftPlaceByLeftItem(c, leftItem) + 1;
int rightPlace = relationshipService.findRightPlaceByRightItem(c, rightItem) + 1; int rightPlace = relationshipService.findRightPlaceByRightItem(c, rightItem) + 1;
Relationship persistedRelationship = relationshipService.create(c, leftItem, rightItem, Relationship persistedRelationship = relationshipService.create(c, leftItem, rightItem,
relationshipType, leftPlace, rightPlace); foundRelationshipType, leftPlace, rightPlace);
relationshipService.update(c, persistedRelationship); relationshipService.update(c, persistedRelationship);
} }
/**
* This method will add RelationshipType objects to the acceptableRelationshipTypes list
* if applicable and valid RelationshipType objects are found. It will also return a boolean indicating
* whether we're dealing with a left Relationship or not
* @param c The relevant DSpace context
* @param entity The Entity for which the RelationshipType has to be checked
* @param relationEntity The other Entity of the Relationship
* @param left Boolean indicating whether the Relationship is left or not
* @param acceptableRelationshipTypes The list of RelationshipType objects that will be added to
* @param rightRelationshipTypesForEntity The list of RelationshipType objects that are possible
* for the right entity
* @param relationshipType The RelationshipType object that we want to check whether it's
* valid to be added or not
* @return A boolean indicating whether the relationship is left or right, will
* be false in this case
* @throws SQLException If something goes wrong
*/
private boolean handleRightLabelEqualityRelationshipTypeElement(Context c, Entity entity, Entity relationEntity,
boolean left,
List<RelationshipType> acceptableRelationshipTypes,
List<RelationshipType>
rightRelationshipTypesForEntity,
RelationshipType relationshipType)
throws SQLException {
if (StringUtils.equalsIgnoreCase(entityService.getType(c, entity).getLabel(),
relationshipType.getRightType().getLabel()) &&
StringUtils.equalsIgnoreCase(entityService.getType(c, relationEntity).getLabel(),
relationshipType.getLeftType().getLabel())) {
for (RelationshipType rightRelationshipType : rightRelationshipTypesForEntity) {
if (StringUtils.equalsIgnoreCase(rightRelationshipType.getLeftType().getLabel(),
relationshipType.getLeftType().getLabel()) ||
StringUtils.equalsIgnoreCase(rightRelationshipType.getRightType().getLabel(),
relationshipType.getLeftType().getLabel())) {
left = false;
acceptableRelationshipTypes.add(relationshipType);
}
}
}
return left;
}
/**
* This method will add RelationshipType objects to the acceptableRelationshipTypes list
* if applicable and valid RelationshipType objects are found. It will also return a boolean indicating
* whether we're dealing with a left Relationship or not
* @param c The relevant DSpace context
* @param entity The Entity for which the RelationshipType has to be checked
* @param relationEntity The other Entity of the Relationship
* @param left Boolean indicating whether the Relationship is left or not
* @param acceptableRelationshipTypes The list of RelationshipType objects that will be added to
* @param leftRelationshipTypesForEntity The list of RelationshipType objects that are possible
* for the left entity
* @param relationshipType The RelationshipType object that we want to check whether it's
* valid to be added or not
* @return A boolean indicating whether the relationship is left or right, will
* be true in this case
* @throws SQLException If something goes wrong
*/
private boolean handleLeftLabelEqualityRelationshipTypeElement(Context c, Entity entity, Entity relationEntity,
boolean left,
List<RelationshipType> acceptableRelationshipTypes,
List<RelationshipType>
leftRelationshipTypesForEntity,
RelationshipType relationshipType)
throws SQLException {
if (StringUtils.equalsIgnoreCase(entityService.getType(c, entity).getLabel(),
relationshipType.getLeftType().getLabel()) &&
StringUtils.equalsIgnoreCase(entityService.getType(c, relationEntity).getLabel(),
relationshipType.getRightType().getLabel())) {
for (RelationshipType leftRelationshipType : leftRelationshipTypesForEntity) {
if (StringUtils.equalsIgnoreCase(leftRelationshipType.getRightType().getLabel(),
relationshipType.getRightType().getLabel()) ||
StringUtils.equalsIgnoreCase(leftRelationshipType.getLeftType().getLabel(),
relationshipType.getRightType().getLabel())) {
left = true;
acceptableRelationshipTypes.add(relationshipType);
}
}
}
return left;
}
/**
* This method will add the relationship.type metadata to the item if an EntityType can be found for the value in
* the values list.
* @param c The relevant DSpace context
* @param item The item to which this metadatavalue will be added
* @param schema The schema for the metadatavalue to be added
* @param element The element for the metadatavalue to be added
* @param qualifier The qualifier for the metadatavalue to be added
* @param language The language for the metadatavalue to be added
* @param values The value on which we'll search for EntityType object and it's the value
* for the metadatavalue that will be created
* @param authorities The authority for the metadatavalue. This will be filled with the ID
* of the found EntityType for the value if it exists
* @param confidences The confidence for the metadatavalue
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
private void handleRelationTypeMetadata(Context c, Item item, String schema, String element, String qualifier,
String language, List<String> values, List<String> authorities,
List<Integer> confidences)
throws SQLException, AuthorizeException {
EntityType entityType = entityTypeService.findByEntityType(c, values.get(0));
if (entityType != null) {
authorities.add(String.valueOf(entityType.getID()));
itemService.clearMetadata(c, item, schema, element, qualifier, language);
itemService.addMetadata(c, item, schema, element, qualifier, language,
values, authorities, confidences);
itemService.update(c, item);
}
}
/** /**
* Compare changes between an items owning collection and mapped collections * Compare changes between an items owning collection and mapped collections
* and what is in the CSV file * and what is in the CSV file
@@ -1573,9 +1425,6 @@ public class MetadataImport {
// Display the changes // Display the changes
displayChanges(changes, true); displayChanges(changes, true);
// Commit the change to the DB
// c.commit();
} }
// Finsh off and tidy up // Finsh off and tidy up
@@ -1590,24 +1439,28 @@ public class MetadataImport {
} }
/** /**
* Gets a copy of the given csv line with all entity references resolved to UUID strings. * Gets a copy of the given csv line with all entity target references resolved to UUID strings.
* Keys being iterated over represent metadatafields or special columns to be processed. * Keys being iterated over represent metadatafields or special columns to be processed.
* *
* @param line the csv line to process. * @param line the csv line to process.
* @return a copy, with all references resolved. * @return a copy, with all references resolved.
* @throws MetadataImportException if there is an error resolving any entity reference. * @throws MetadataImportException if there is an error resolving any entity target reference.
*/ */
public DSpaceCSVLine resolveEntityRefs(DSpaceCSVLine line) throws MetadataImportException { public DSpaceCSVLine resolveEntityRefs(DSpaceCSVLine line) throws MetadataImportException {
DSpaceCSVLine newLine = new DSpaceCSVLine(line.getID()); DSpaceCSVLine newLine = new DSpaceCSVLine(line.getID());
UUID originId = evaluateOriginId(line.getID());
for (String key : line.keys()) { for (String key : line.keys()) {
// If a key represents a relation field attempt to resolve the reference from the csvRefMap // If a key represents a relation field attempt to resolve the target reference from the csvRefMap
if (key.split("\\.")[0].equalsIgnoreCase("relation")) { if (key.split("\\.")[0].equalsIgnoreCase("relation")) {
if (line.get(key).size() > 0) { if (line.get(key).size() > 0) {
for (String val : line.get(key)) { for (String val : line.get(key)) {
// Attempt to resolve the relation reference // Attempt to resolve the relation target reference
// These can be a UUID, metadata reference or rowName reference // These can be a UUID, metadata target reference or rowName target reference
String uuid = resolveEntityRef(c, val).toString(); String uuid = resolveEntityRef(c, val).toString();
newLine.add(key, uuid); newLine.add(key, uuid);
//Entity refs have been resolved / placeholdered
//Populate the EntityRelationMap
populateEntityRelationMap(uuid, key, originId.toString());
} }
} }
} else { } else {
@@ -1622,27 +1475,59 @@ public class MetadataImport {
} }
} }
} }
return newLine; return newLine;
} }
/** /**
* Populates the csvRefMap and csvRowMap for the given csv line. * Populate the entityRelationMap with all target references and it's asscoiated typeNames
* to their respective origins
*
* @param refUUID the target reference UUID for the relation
* @param relationField the field of the typeNames to relate from
*/
private void populateEntityRelationMap(String refUUID, String relationField, String originId) {
HashMap<String, ArrayList<String>> typeNames = null;
if (entityRelationMap.get(refUUID) == null) {
typeNames = new HashMap<>();
ArrayList<String> originIds = new ArrayList<>();
originIds.add(originId);
typeNames.put(relationField, originIds);
entityRelationMap.put(refUUID, typeNames);
} else {
typeNames = entityRelationMap.get(refUUID);
if (typeNames.get(relationField) == null) {
ArrayList<String> originIds = new ArrayList<>();
originIds.add(originId);
typeNames.put(relationField, originIds);
} else {
ArrayList<String> originIds = typeNames.get(relationField);
originIds.add(originId);
typeNames.put(relationField, originIds);
}
entityRelationMap.put(refUUID, typeNames);
}
}
/**
* Populates the csvRefMap, csvRowMap, and entityTypeMap for the given csv line.
* *
* The csvRefMap is an index that keeps track of which rows have a specific value for * The csvRefMap is an index that keeps track of which rows have a specific value for
* a specific metadata field or the special "rowName" column. This is used to help resolve indirect * a specific metadata field or the special "rowName" column. This is used to help resolve indirect
* entity references in the same CSV. * entity target references in the same CSV.
* *
* The csvRowMap is a row number to UUID map, and contains an entry for every row that has * The csvRowMap is a row number to UUID map, and contains an entry for every row that has
* been processed so far which has a known (minted) UUID for its item. This is used to help complete * been processed so far which has a known (minted) UUID for its item. This is used to help complete
* the resolution after the row number has been determined. * the resolution after the row number has been determined.
* *
* @param line the csv line. * @param line the csv line.
* @param rowNumber the row number.
* @param uuid the uuid of the item, which may be null if it has not been minted yet. * @param uuid the uuid of the item, which may be null if it has not been minted yet.
*/ */
private void populateRefAndRowMap(DSpaceCSVLine line, int rowNumber, @Nullable UUID uuid) { private void populateRefAndRowMap(DSpaceCSVLine line, @Nullable UUID uuid) {
if (uuid != null) { if (uuid != null) {
csvRowMap.put(rowNumber, uuid); csvRowMap.put(rowCount, uuid);
} else {
csvRowMap.put(rowCount, new UUID(0, rowCount));
} }
for (String key : line.keys()) { for (String key : line.keys()) {
if (key.contains(".") && !key.split("\\.")[0].equalsIgnoreCase("relation") || if (key.contains(".") && !key.split("\\.")[0].equalsIgnoreCase("relation") ||
@@ -1654,22 +1539,31 @@ public class MetadataImport {
rowNums = new HashSet<>(); rowNums = new HashSet<>();
csvRefMap.put(valueKey, rowNums); csvRefMap.put(valueKey, rowNums);
} }
rowNums.add(rowNumber); rowNums.add(rowCount);
}
}
//Populate entityTypeMap
if (key.equalsIgnoreCase("relationship.type") && line.get(key).size() > 0) {
if (uuid == null) {
entityTypeMap.put(new UUID(0, rowCount), line.get(key).get(0));
} else {
entityTypeMap.put(uuid, line.get(key).get(0));
} }
} }
} }
} }
/** /**
* Gets the UUID of the item indicated by the given reference, which may be a direct UUID string, a row reference * Gets the UUID of the item indicated by the given target reference,
* which may be a direct UUID string, a row reference
* of the form rowName:VALUE, or a metadata value reference of the form schema.element[.qualifier]:VALUE. * of the form rowName:VALUE, or a metadata value reference of the form schema.element[.qualifier]:VALUE.
* *
* The reference may refer to a previously-processed item in the CSV or an item in the database. * The reference may refer to a previously-processed item in the CSV or an item in the database.
* *
* @param context the context to use. * @param context the context to use.
* @param reference the reference which may be a UUID, metadata reference, or rowName reference. * @param reference the target reference which may be a UUID, metadata reference, or rowName reference.
* @return the uuid. * @return the uuid.
* @throws MetadataImportException if the reference is malformed or ambiguous (refers to multiple items). * @throws MetadataImportException if the target reference is malformed or ambiguous (refers to multiple items).
*/ */
private UUID resolveEntityRef(Context context, String reference) throws MetadataImportException { private UUID resolveEntityRef(Context context, String reference) throws MetadataImportException {
// value reference // value reference
@@ -1679,7 +1573,8 @@ public class MetadataImport {
try { try {
return UUID.fromString(reference); return UUID.fromString(reference);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new MetadataImportException("Not a UUID or indirect entity reference: '" + reference + "'"); throw new MetadataImportException("Error in CSV row " + rowCount + ":\n" +
"Not a UUID or indirect entity reference: '" + reference + "'");
} }
} else if (!reference.startsWith("rowName:") ) { // Not a rowName ref; so it's a metadata value reference } else if (!reference.startsWith("rowName:") ) { // Not a rowName ref; so it's a metadata value reference
MetadataValueService metadataValueService = ContentServiceFactory.getInstance().getMetadataValueService(); MetadataValueService metadataValueService = ContentServiceFactory.getInstance().getMetadataValueService();
@@ -1689,7 +1584,8 @@ public class MetadataImport {
String mfValue = reference.substring(i + 1); String mfValue = reference.substring(i + 1);
String mf[] = reference.substring(0, i).split("\\."); String mf[] = reference.substring(0, i).split("\\.");
if (mf.length < 2) { if (mf.length < 2) {
throw new MetadataImportException("Bad metadata field in reference: '" + reference throw new MetadataImportException("Error in CSV row " + rowCount + ":\n" +
"Bad metadata field in reference: '" + reference
+ "' (expected syntax is schema.element[.qualifier])"); + "' (expected syntax is schema.element[.qualifier])");
} }
String schema = mf[0]; String schema = mf[0];
@@ -1702,11 +1598,13 @@ public class MetadataImport {
MetadataValue mdvVal = mdv.next(); MetadataValue mdvVal = mdv.next();
uuid = mdvVal.getDSpaceObject().getID(); uuid = mdvVal.getDSpaceObject().getID();
if (mdv.hasNext()) { if (mdv.hasNext()) {
throw new MetadataImportException("Ambiguous reference; multiple matches in db: " + reference); throw new MetadataImportException("Error in CSV row " + rowCount + ":\n" +
"Ambiguous reference; multiple matches in db: " + reference);
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new MetadataImportException("Error looking up item by metadata reference: " + reference, e); throw new MetadataImportException("Error in CSV row " + rowCount + ":\n" +
"Error looking up item by metadata reference: " + reference, e);
} }
} }
// Lookup UUIDs that may have already been processed into the csvRefMap // Lookup UUIDs that may have already been processed into the csvRefMap
@@ -1714,20 +1612,23 @@ public class MetadataImport {
// See getMatchingCSVUUIDs() for how the reference param is sourced from the csvRefMap // See getMatchingCSVUUIDs() for how the reference param is sourced from the csvRefMap
Set<UUID> csvUUIDs = getMatchingCSVUUIDs(reference); Set<UUID> csvUUIDs = getMatchingCSVUUIDs(reference);
if (csvUUIDs.size() > 1) { if (csvUUIDs.size() > 1) {
throw new MetadataImportException("Ambiguous reference; multiple matches in csv: " + reference); throw new MetadataImportException("Error in CSV row " + rowCount + ":\n" +
"Ambiguous reference; multiple matches in csv: " + reference);
} else if (csvUUIDs.size() == 1) { } else if (csvUUIDs.size() == 1) {
UUID csvUUID = csvUUIDs.iterator().next(); UUID csvUUID = csvUUIDs.iterator().next();
if (csvUUID.equals(uuid)) { if (csvUUID.equals(uuid)) {
return uuid; // one match from csv and db (same item) return uuid; // one match from csv and db (same item)
} else if (uuid != null) { } else if (uuid != null) {
throw new MetadataImportException("Ambiguous reference; multiple matches in db and csv: " + reference); throw new MetadataImportException("Error in CSV row " + rowCount + ":\n" +
"Ambiguous reference; multiple matches in db and csv: " + reference);
} else { } else {
return csvUUID; // one match from csv return csvUUID; // one match from csv
} }
} else { // size == 0; the reference does not exist throw an error } else { // size == 0; the reference does not exist throw an error
if (uuid == null) { if (uuid == null) {
throw new MetadataImportException("No matches found for reference: " + reference throw new MetadataImportException("Error in CSV row " + rowCount + ":\n" +
+ ", Keep in mind you can only reference entries that are listed before " + "No matches found for reference: " + reference
+ "\nKeep in mind you can only reference entries that are listed before " +
"this one within the CSV."); "this one within the CSV.");
} else { } else {
return uuid; // one match from db return uuid; // one match from db
@@ -1767,4 +1668,187 @@ public class MetadataImport {
} }
} }
/**
* Return a UUID of the origin in process or a placeholder for the origin to be evaluated later
*
* @param originId UUID of the origin
* @return the UUID of the item or UUID placeholder
*/
private UUID evaluateOriginId(@Nullable UUID originId) {
if (originId != null) {
return originId;
} else {
return new UUID(0, rowCount);
}
}
/**
* Validate every relation modification expressed in the CSV.
*
*/
private void validateExpressedRelations() throws MetadataImportException {
for (String targetUUID : entityRelationMap.keySet()) {
String targetType = null;
try {
// Get the type of reference. Attempt lookup in processed map first before looking in archive.
if (entityTypeMap.get(UUID.fromString(targetUUID)) != null) {
targetType = entityTypeService.
findByEntityType(c, entityTypeMap.get(UUID.fromString(targetUUID))).getLabel();
} else {
// Target item may be archived; check there.
// Add to errors if Realtionship.type cannot be derived
Item targetItem = null;
if (itemService.find(c, UUID.fromString(targetUUID)) != null) {
targetItem = itemService.find(c, UUID.fromString(targetUUID));
List<MetadataValue> relTypes = itemService.
getMetadata(targetItem, "relationship", "type", null, Item.ANY);
String relTypeValue = null;
if (relTypes.size() > 0) {
relTypeValue = relTypes.get(0).getValue();
targetType = entityTypeService.findByEntityType(c, relTypeValue).getLabel();
} else {
relationValidationErrors.add("Cannot resolve Entity type for target UUID: " +
targetUUID);
}
} else {
relationValidationErrors.add("Cannot resolve Entity type for target UUID: " +
targetUUID);
}
}
if (targetType == null) {
continue;
}
// Get typeNames for each origin referer of this target.
for (String typeName : entityRelationMap.get(targetUUID).keySet()) {
// Resolve Entity Type for each origin referer.
for (String originRefererUUID : entityRelationMap.get(targetUUID).get(typeName)) {
// Evaluate row number for origin referer.
String originRow = "N/A";
if (csvRowMap.containsValue(UUID.fromString(originRefererUUID))) {
for (int key : csvRowMap.keySet()) {
if (csvRowMap.get(key).toString().equalsIgnoreCase(originRefererUUID)) {
originRow = key + "";
break;
}
}
}
String originType = "";
// Validate target type and origin type pairing with typeName or add to errors.
// Attempt lookup in processed map first before looking in archive.
if (entityTypeMap.get(UUID.fromString(originRefererUUID)) != null) {
originType = entityTypeMap.get(UUID.fromString(originRefererUUID));
validateTypesByTypeByTypeName(targetType, originType, typeName, originRow);
} else {
// Origin item may be archived; check there.
// Add to errors if Realtionship.type cannot be derived.
Item originItem = null;
if (itemService.find(c, UUID.fromString(targetUUID)) != null) {
originItem = itemService.find(c, UUID.fromString(originRefererUUID));
List<MetadataValue> relTypes = itemService.
getMetadata(originItem, "relationship", "type", null, Item.ANY);
String relTypeValue = null;
if (relTypes.size() > 0) {
relTypeValue = relTypes.get(0).getValue();
originType = entityTypeService.findByEntityType(c, relTypeValue).getLabel();
validateTypesByTypeByTypeName(targetType, originType, typeName, originRow);
} else {
relationValidationErrors.add("Error on CSV row " + originRow + ":" + "\n" +
"Cannot resolve Entity type for reference: "
+ originRefererUUID);
}
} else {
relationValidationErrors.add("Error on CSV row " + originRow + ":" + "\n" +
"Cannot resolve Entity type for reference: "
+ originRefererUUID + " in row: " + originRow );
}
}
}
}
} catch (SQLException sqle) {
throw new MetadataImportException("Error interacting with database!", sqle);
}
} // If relationValidationErrors is empty all described relationships are valid.
if (!relationValidationErrors.isEmpty()) {
StringBuilder errors = new StringBuilder();
for (String error : relationValidationErrors) {
errors.append(error + "\n");
}
throw new MetadataImportException("Error validating relationships: \n" + errors);
}
}
/**
* Generates a list of potenital Relationship Types given a typeName and attempts to match the given
* targetType and originType to a Relationship Type in the list.
*
* @param targetType entity type of target.
* @param originType entity type of origin referer.
* @param typeName left or right typeName of the respective Relationship.
* @return the UUID of the item.
*/
private void validateTypesByTypeByTypeName(String targetType, String originType, String typeName, String originRow)
throws MetadataImportException {
try {
RelationshipType foundRelationshipType = null;
List<RelationshipType> relationshipTypeList = relationshipTypeService.
findByLeftwardOrRightwardTypeName(c, typeName.split("\\.")[1]);
// Validate described relationship form the CSV.
foundRelationshipType = matchRelationshipType(relationshipTypeList, targetType, originType, typeName);
if (foundRelationshipType == null) {
relationValidationErrors.add("Error on CSV row " + originRow + ":" + "\n" +
"No Relationship type found for:\n" +
"Target type: " + targetType + "\n" +
"Origin referer type: " + originType + "\n" +
"with typeName: " + typeName + " for type: " + originType);
}
} catch (SQLException sqle) {
throw new MetadataImportException("Error interacting with database!", sqle);
}
}
/**
* Matches two Entity types to a Relationship Type from a set of Relationship Types.
*
* @param relTypes set of Relationship Types.
* @param targetType entity type of target.
* @param originType entity type of origin referer.
* @return null or matched Relationship Type.
*/
private RelationshipType matchRelationshipType(List<RelationshipType> relTypes,
String targetType, String originType, String originTypeName) {
RelationshipType foundRelationshipType = null;
if (originTypeName.split("\\.").length > 1) {
originTypeName = originTypeName.split("\\.")[1];
}
for (RelationshipType relationshipType : relTypes) {
// Is origin type leftward or righward
boolean isLeft = false;
if (relationshipType.getLeftType().getLabel().equalsIgnoreCase(originType)) {
isLeft = true;
}
if (isLeft) {
// Validate typeName reference
if (!relationshipType.getLeftwardType().equalsIgnoreCase(originTypeName)) {
continue;
}
if (relationshipType.getLeftType().getLabel().equalsIgnoreCase(originType) &&
relationshipType.getRightType().getLabel().equalsIgnoreCase(targetType)) {
foundRelationshipType = relationshipType;
}
} else {
if (!relationshipType.getRightwardType().equalsIgnoreCase(originTypeName)) {
continue;
}
if (relationshipType.getLeftType().getLabel().equalsIgnoreCase(targetType) &&
relationshipType.getRightType().getLabel().equalsIgnoreCase(originType)) {
foundRelationshipType = relationshipType;
}
}
}
return foundRelationshipType;
}
} }

View File

@@ -272,9 +272,8 @@ public class Harvest {
targetCollection = (Collection) dso; targetCollection = (Collection) dso;
} }
} else { } else {
// not a handle, try and treat it as an integer collection database ID // not a handle, try and treat it as an collection database UUID
System.out.println("Looking up by id: " + collectionID + ", parsed as '" + Integer System.out.println("Looking up by UUID: " + collectionID + ", " + "in context: " + context);
.parseInt(collectionID) + "', " + "in context: " + context);
targetCollection = collectionService.find(context, UUID.fromString(collectionID)); targetCollection = collectionService.find(context, UUID.fromString(collectionID));
} }
} }
@@ -460,7 +459,7 @@ public class Harvest {
List<String> errors; List<String> errors;
System.out.print("Testing basic PMH access: "); System.out.print("Testing basic PMH access: ");
errors = OAIHarvester.verifyOAIharvester(server, set, errors = harvestedCollectionService.verifyOAIharvester(server, set,
(null != metadataFormat) ? metadataFormat : "dc", false); (null != metadataFormat) ? metadataFormat : "dc", false);
if (errors.isEmpty()) { if (errors.isEmpty()) {
System.out.println("OK"); System.out.println("OK");
@@ -471,7 +470,7 @@ public class Harvest {
} }
System.out.print("Testing ORE support: "); System.out.print("Testing ORE support: ");
errors = OAIHarvester.verifyOAIharvester(server, set, errors = harvestedCollectionService.verifyOAIharvester(server, set,
(null != metadataFormat) ? metadataFormat : "dc", true); (null != metadataFormat) ? metadataFormat : "dc", true);
if (errors.isEmpty()) { if (errors.isEmpty()) {
System.out.println("OK"); System.out.println("OK");

View File

@@ -128,8 +128,8 @@ public class InitializeEntities {
String leftType = eElement.getElementsByTagName("leftType").item(0).getTextContent(); String leftType = eElement.getElementsByTagName("leftType").item(0).getTextContent();
String rightType = eElement.getElementsByTagName("rightType").item(0).getTextContent(); String rightType = eElement.getElementsByTagName("rightType").item(0).getTextContent();
String leftLabel = eElement.getElementsByTagName("leftLabel").item(0).getTextContent(); String leftwardType = eElement.getElementsByTagName("leftwardType").item(0).getTextContent();
String rightLabel = eElement.getElementsByTagName("rightLabel").item(0).getTextContent(); String rightwardType = eElement.getElementsByTagName("rightwardType").item(0).getTextContent();
NodeList leftCardinalityList = eElement.getElementsByTagName("leftCardinality"); NodeList leftCardinalityList = eElement.getElementsByTagName("leftCardinality");
@@ -154,7 +154,7 @@ public class InitializeEntities {
rightCardinalityMax = getString(rightCardinalityMax,(Element) node, "max"); rightCardinalityMax = getString(rightCardinalityMax,(Element) node, "max");
} }
populateRelationshipType(context, leftType, rightType, leftLabel, rightLabel, populateRelationshipType(context, leftType, rightType, leftwardType, rightwardType,
leftCardinalityMin, leftCardinalityMax, leftCardinalityMin, leftCardinalityMax,
rightCardinalityMin, rightCardinalityMax); rightCardinalityMin, rightCardinalityMax);
@@ -173,8 +173,8 @@ public class InitializeEntities {
return leftCardinalityMin; return leftCardinalityMin;
} }
private void populateRelationshipType(Context context, String leftType, String rightType, String leftLabel, private void populateRelationshipType(Context context, String leftType, String rightType, String leftwardType,
String rightLabel, String leftCardinalityMin, String leftCardinalityMax, String rightwardType, String leftCardinalityMin, String leftCardinalityMax,
String rightCardinalityMin, String rightCardinalityMax) String rightCardinalityMin, String rightCardinalityMax)
throws SQLException, AuthorizeException { throws SQLException, AuthorizeException {
@@ -211,9 +211,9 @@ public class InitializeEntities {
rightCardinalityMaxInteger = null; rightCardinalityMaxInteger = null;
} }
RelationshipType relationshipType = relationshipTypeService RelationshipType relationshipType = relationshipTypeService
.findbyTypesAndLabels(context, leftEntityType, rightEntityType, leftLabel, rightLabel); .findbyTypesAndTypeName(context, leftEntityType, rightEntityType, leftwardType, rightwardType);
if (relationshipType == null) { if (relationshipType == null) {
relationshipTypeService.create(context, leftEntityType, rightEntityType, leftLabel, rightLabel, relationshipTypeService.create(context, leftEntityType, rightEntityType, leftwardType, rightwardType,
leftCardinalityMinInteger, leftCardinalityMaxInteger, leftCardinalityMinInteger, leftCardinalityMaxInteger,
rightCardinalityMinInteger, rightCardinalityMaxInteger); rightCardinalityMinInteger, rightCardinalityMaxInteger);
} else { } else {

View File

@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.impl.HttpSolrClient;
@@ -39,9 +40,9 @@ public class AuthoritySolrServiceImpl implements AuthorityIndexingService, Autho
/** /**
* Non-Static CommonsHttpSolrServer for processing indexing events. * Non-Static CommonsHttpSolrServer for processing indexing events.
*/ */
protected HttpSolrClient solr = null; protected SolrClient solr = null;
protected HttpSolrClient getSolr() protected SolrClient getSolr()
throws MalformedURLException, SolrServerException, IOException { throws MalformedURLException, SolrServerException, IOException {
if (solr == null) { if (solr == null) {
@@ -49,12 +50,14 @@ public class AuthoritySolrServiceImpl implements AuthorityIndexingService, Autho
log.debug("Solr authority URL: " + solrService); log.debug("Solr authority URL: " + solrService);
solr = new HttpSolrClient.Builder(solrService).build(); HttpSolrClient solrServer = new HttpSolrClient.Builder(solrService).build();
solr.setBaseURL(solrService); solrServer.setBaseURL(solrService);
SolrQuery solrQuery = new SolrQuery().setQuery("*:*"); SolrQuery solrQuery = new SolrQuery().setQuery("*:*");
solr.query(solrQuery); solrServer.query(solrQuery);
solr = solrServer;
} }
return solr; return solr;

View File

@@ -275,7 +275,7 @@ public class BitstreamFormat implements Serializable, ReloadableEntity<Integer>
return false; return false;
} }
final BitstreamFormat otherBitstreamFormat = (BitstreamFormat) other; final BitstreamFormat otherBitstreamFormat = (BitstreamFormat) other;
if (this.getID() != otherBitstreamFormat.getID()) { if (!this.getID().equals(otherBitstreamFormat.getID())) {
return false; return false;
} }

View File

@@ -12,7 +12,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.dspace.content.service.EntityService; import org.dspace.content.service.EntityService;
import org.dspace.content.service.EntityTypeService; import org.dspace.content.service.EntityTypeService;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
@@ -37,8 +36,15 @@ public class EntityServiceImpl implements EntityService {
@Override @Override
public Entity findByItemId(Context context, UUID itemId) throws SQLException { public Entity findByItemId(Context context, UUID itemId) throws SQLException {
return findByItemId(context, itemId, -1, -1);
}
@Override
public Entity findByItemId(Context context, UUID itemId, Integer limit, Integer offset) throws SQLException {
Item item = itemService.find(context, itemId); Item item = itemService.find(context, itemId);
List<Relationship> relationshipList = relationshipService.findByItem(context, item); List<Relationship> relationshipList = relationshipService.findByItem(context, item, limit, offset);
return new Entity(item, relationshipList); return new Entity(item, relationshipList);
} }
@@ -78,65 +84,61 @@ public class EntityServiceImpl implements EntityService {
} }
@Override @Override
public List<Relationship> getRelationsByLabel(Context context, String label) throws SQLException { public List<Relationship> getRelationsByTypeName(Context context, String typeName) throws SQLException {
List<Relationship> listToReturn = new LinkedList<>(); return getRelationsByTypeName(context, typeName, -1, -1);
List<Relationship> relationshipList = relationshipService.findAll(context); }
for (Relationship relationship : relationshipList) {
RelationshipType relationshipType = relationship.getRelationshipType(); @Override
if (StringUtils.equals(relationshipType.getLeftLabel(),label) || public List<Relationship> getRelationsByTypeName(Context context, String typeName, Integer limit, Integer offset)
StringUtils.equals(relationshipType.getRightLabel(),label)) { throws SQLException {
listToReturn.add(relationship); return relationshipService.findByTypeName(context, typeName, limit, offset);
}
}
return listToReturn;
} }
@Override @Override
public List<RelationshipType> getAllRelationshipTypes(Context context, Entity entity) throws SQLException { public List<RelationshipType> getAllRelationshipTypes(Context context, Entity entity) throws SQLException {
EntityType entityType = this.getType(context, entity);
List<RelationshipType> listToReturn = new LinkedList<>(); return getAllRelationshipTypes(context, entity, -1, -1);
for (RelationshipType relationshipType : relationshipTypeService.findAll(context)) { }
if (relationshipType.getLeftType().getID() == entityType.getID() ||
relationshipType.getRightType().getID() == entityType.getID()) { @Override
listToReturn.add(relationshipType); public List<RelationshipType> getAllRelationshipTypes(Context context, Entity entity, Integer limit, Integer offset)
} throws SQLException {
} return relationshipTypeService.findByEntityType(context, this.getType(context, entity), limit, offset);
return listToReturn;
} }
@Override @Override
public List<RelationshipType> getLeftRelationshipTypes(Context context, Entity entity) throws SQLException { public List<RelationshipType> getLeftRelationshipTypes(Context context, Entity entity) throws SQLException {
EntityType entityType = this.getType(context, entity);
List<RelationshipType> listToReturn = new LinkedList<>(); return getLeftRelationshipTypes(context, entity, true, -1, -1);
for (RelationshipType relationshipType : relationshipTypeService.findAll(context)) { }
if (relationshipType.getLeftType().getID() == entityType.getID()) {
listToReturn.add(relationshipType); @Override
} public List<RelationshipType> getLeftRelationshipTypes(Context context, Entity entity, boolean isLeft,
} Integer limit, Integer offset) throws SQLException {
return listToReturn; return relationshipTypeService.findByEntityType(context, this.getType(context, entity), isLeft, limit, offset);
} }
@Override @Override
public List<RelationshipType> getRightRelationshipTypes(Context context, Entity entity) throws SQLException { public List<RelationshipType> getRightRelationshipTypes(Context context, Entity entity) throws SQLException {
EntityType entityType = this.getType(context, entity);
List<RelationshipType> listToReturn = new LinkedList<>(); return getRightRelationshipTypes(context, entity, false, -1, -1);
for (RelationshipType relationshipType : relationshipTypeService.findAll(context)) {
if (relationshipType.getRightType().getID() == entityType.getID()) {
listToReturn.add(relationshipType);
}
}
return listToReturn;
} }
@Override @Override
public List<RelationshipType> getRelationshipTypesByLabel(Context context, String label) throws SQLException { public List<RelationshipType> getRightRelationshipTypes(Context context, Entity entity, boolean isLeft,
List<RelationshipType> listToReturn = new LinkedList<>(); Integer limit, Integer offset) throws SQLException {
for (RelationshipType relationshipType : relationshipTypeService.findAll(context)) {
if (StringUtils.equals(relationshipType.getLeftLabel(),label) || return relationshipTypeService.findByEntityType(context, this.getType(context, entity), isLeft, limit, offset);
StringUtils.equals(relationshipType.getRightLabel(),label)) { }
listToReturn.add(relationshipType);
} @Override
} public List<RelationshipType> getRelationshipTypesByTypeName(Context context, String type) throws SQLException {
return listToReturn; return getRelationshipTypesByTypeName(context, type, -1, -1);
}
@Override
public List<RelationshipType> getRelationshipTypesByTypeName(Context context, String typeName,
Integer limit, Integer offset) throws SQLException {
return relationshipTypeService.findByLeftwardOrRightwardTypeName(context, typeName, limit, offset);
} }
} }

View File

@@ -28,13 +28,20 @@ public class EntityTypeServiceImpl implements EntityTypeService {
protected AuthorizeService authorizeService; protected AuthorizeService authorizeService;
@Override @Override
public EntityType findByEntityType(Context context,String entityType) throws SQLException { public EntityType findByEntityType(Context context, String entityType) throws SQLException {
return entityTypeDAO.findByEntityType(context, entityType); return entityTypeDAO.findByEntityType(context, entityType);
} }
@Override @Override
public List<EntityType> findAll(Context context) throws SQLException { public List<EntityType> findAll(Context context) throws SQLException {
return entityTypeDAO.findAll(context, EntityType.class);
return findAll(context, -1, -1);
}
@Override
public List<EntityType> findAll(Context context, Integer limit, Integer offset) throws SQLException {
return entityTypeDAO.findAll(context, EntityType.class, limit, offset);
} }
@Override @Override

View File

@@ -13,11 +13,9 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -44,7 +42,6 @@ import org.dspace.content.service.ItemService;
import org.dspace.content.service.MetadataSchemaService; import org.dspace.content.service.MetadataSchemaService;
import org.dspace.content.service.RelationshipService; import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.WorkspaceItemService; import org.dspace.content.service.WorkspaceItemService;
import org.dspace.content.virtual.VirtualMetadataConfiguration;
import org.dspace.content.virtual.VirtualMetadataPopulator; import org.dspace.content.virtual.VirtualMetadataPopulator;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
@@ -117,6 +114,9 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
@Autowired(required = true) @Autowired(required = true)
protected VirtualMetadataPopulator virtualMetadataPopulator; protected VirtualMetadataPopulator virtualMetadataPopulator;
@Autowired(required = true)
private RelationshipMetadataService relationshipMetadataService;
protected ItemServiceImpl() { protected ItemServiceImpl() {
super(); super();
} }
@@ -1344,27 +1344,6 @@ prevent the generation of resource policy entry values with null dspace_object a
return this.getMetadata(item, schema, element, qualifier, lang, true); return this.getMetadata(item, schema, element, qualifier, lang, true);
} }
@Override
public List<RelationshipMetadataValue> getRelationshipMetadata(Item item, boolean enableVirtualMetadata) {
Context context = new Context();
List<RelationshipMetadataValue> fullMetadataValueList = new LinkedList<>();
try {
List<MetadataValue> list = item.getMetadata();
String entityType = getEntityTypeStringFromMetadata(list);
if (StringUtils.isNotBlank(entityType)) {
List<Relationship> relationships = relationshipService.findByItem(context, item);
for (Relationship relationship : relationships) {
fullMetadataValueList
.addAll(handleItemRelationship(context, item, entityType, relationship, enableVirtualMetadata));
}
}
} catch (SQLException e) {
log.error("Lookup for Relationships for item with uuid: " + item.getID() + " caused DSpace to crash", e);
}
return fullMetadataValueList;
}
@Override @Override
public List<MetadataValue> getMetadata(Item item, String schema, String element, String qualifier, String lang, public List<MetadataValue> getMetadata(Item item, String schema, String element, String qualifier, String lang,
boolean enableVirtualMetadata) { boolean enableVirtualMetadata) {
@@ -1372,7 +1351,8 @@ prevent the generation of resource policy entry values with null dspace_object a
//except for relation.type which is the type of item in the model //except for relation.type which is the type of item in the model
if (StringUtils.equals(schema, MetadataSchemaEnum.RELATION.getName()) && !StringUtils.equals(element, "type")) { if (StringUtils.equals(schema, MetadataSchemaEnum.RELATION.getName()) && !StringUtils.equals(element, "type")) {
List<RelationshipMetadataValue> relationMetadata = getRelationshipMetadata(item, false); List<RelationshipMetadataValue> relationMetadata = relationshipMetadataService
.getRelationshipMetadata(item, false);
List<MetadataValue> listToReturn = new LinkedList<>(); List<MetadataValue> listToReturn = new LinkedList<>();
for (MetadataValue metadataValue : relationMetadata) { for (MetadataValue metadataValue : relationMetadata) {
if (StringUtils.equals(metadataValue.getMetadataField().getElement(), element)) { if (StringUtils.equals(metadataValue.getMetadataField().getElement(), element)) {
@@ -1388,7 +1368,7 @@ prevent the generation of resource policy entry values with null dspace_object a
List<MetadataValue> fullMetadataValueList = new LinkedList<>(); List<MetadataValue> fullMetadataValueList = new LinkedList<>();
if (enableVirtualMetadata) { if (enableVirtualMetadata) {
fullMetadataValueList.addAll(getRelationshipMetadata(item, true)); fullMetadataValueList.addAll(relationshipMetadataService.getRelationshipMetadata(item, true));
} }
fullMetadataValueList.addAll(dbMetadataValues); fullMetadataValueList.addAll(dbMetadataValues);
@@ -1409,7 +1389,7 @@ prevent the generation of resource policy entry values with null dspace_object a
* This method will sort the List of MetadataValue objects based on the MetadataSchema, MetadataField Element, * This method will sort the List of MetadataValue objects based on the MetadataSchema, MetadataField Element,
* MetadataField Qualifier and MetadataField Place in that order. * MetadataField Qualifier and MetadataField Place in that order.
* @param listToReturn The list to be sorted * @param listToReturn The list to be sorted
* @return The list sorted on those criteria * @return The list sorted on those criteria
*/ */
private List<MetadataValue> sortMetadataValueList(List<MetadataValue> listToReturn) { private List<MetadataValue> sortMetadataValueList(List<MetadataValue> listToReturn) {
Comparator<MetadataValue> comparator = Comparator.comparing( Comparator<MetadataValue> comparator = Comparator.comparing(
@@ -1427,137 +1407,5 @@ prevent the generation of resource policy entry values with null dspace_object a
return listToReturn; return listToReturn;
} }
//This method processes the Relationship of an Item and will return a list of RelationshipMetadataValue objects
//that are generated for this specfic relationship for the item through the config in VirtualMetadataPopulator
private List<RelationshipMetadataValue> handleItemRelationship(Context context, Item item, String entityType,
Relationship relationship,
boolean enableVirtualMetadata)
throws SQLException {
List<RelationshipMetadataValue> resultingMetadataValueList = new LinkedList<>();
RelationshipType relationshipType = relationship.getRelationshipType();
HashMap<String, VirtualMetadataConfiguration> hashMaps;
String relationName = "";
Item otherItem = null;
int place = 0;
if (StringUtils.equals(relationshipType.getLeftType().getLabel(), entityType)) {
hashMaps = virtualMetadataPopulator.getMap().get(relationshipType.getLeftLabel());
otherItem = relationship.getRightItem();
relationName = relationship.getRelationshipType().getLeftLabel();
place = relationship.getLeftPlace();
} else if (StringUtils.equals(relationshipType.getRightType().getLabel(), entityType)) {
hashMaps = virtualMetadataPopulator.getMap().get(relationshipType.getRightLabel());
otherItem = relationship.getLeftItem();
relationName = relationship.getRelationshipType().getRightLabel();
place = relationship.getRightPlace();
} else {
//No virtual metadata can be created
return resultingMetadataValueList;
}
if (hashMaps != null && enableVirtualMetadata) {
resultingMetadataValueList.addAll(handleRelationshipTypeMetadataMapping(context, item, hashMaps,
otherItem, relationName,
relationship.getID(), place));
}
RelationshipMetadataValue relationMetadataFromOtherItem =
getRelationMetadataFromOtherItem(context, otherItem, relationName, relationship.getID(), place);
if (relationMetadataFromOtherItem != null) {
resultingMetadataValueList.add(relationMetadataFromOtherItem);
}
return resultingMetadataValueList;
}
//This method will retrieve a list of RelationshipMetadataValue objects based on the config passed along in the
//hashmaps parameter. The beans will be used to retrieve the values for the RelationshipMetadataValue objects
//and the keys of the hashmap will be used to construct the RelationshipMetadataValue object.
private List<RelationshipMetadataValue> handleRelationshipTypeMetadataMapping(Context context, Item item,
HashMap<String, VirtualMetadataConfiguration> hashMaps,
Item otherItem, String relationName,
Integer relationshipId, int place)
throws SQLException {
List<RelationshipMetadataValue> resultingMetadataValueList = new LinkedList<>();
for (Map.Entry<String, VirtualMetadataConfiguration> entry : hashMaps.entrySet()) {
String key = entry.getKey();
VirtualMetadataConfiguration virtualBean = entry.getValue();
for (String value : virtualBean.getValues(context, otherItem)) {
RelationshipMetadataValue metadataValue = constructMetadataValue(context, key);
if (metadataValue != null) {
metadataValue = constructResultingMetadataValue(item, value, metadataValue, relationshipId);
metadataValue.setUseForPlace(virtualBean.getUseForPlace());
metadataValue.setPlace(place);
if (StringUtils.isNotBlank(metadataValue.getValue())) {
resultingMetadataValueList.add(metadataValue);
}
}
}
}
return resultingMetadataValueList;
}
private RelationshipMetadataValue getRelationMetadataFromOtherItem(Context context, Item otherItem,
String relationName,
Integer relationshipId, int place) {
RelationshipMetadataValue metadataValue = constructMetadataValue(context,
MetadataSchemaEnum.RELATION
.getName() + "." + relationName);
if (metadataValue != null) {
metadataValue.setAuthority(Constants.VIRTUAL_AUTHORITY_PREFIX + relationshipId);
metadataValue.setValue(otherItem.getID().toString());
metadataValue.setPlace(place);
return metadataValue;
}
return null;
}
private String getEntityTypeStringFromMetadata(List<MetadataValue> list) {
for (MetadataValue mdv : list) {
if (StringUtils.equals(mdv.getMetadataField().getMetadataSchema().getName(),
"relationship")
&& StringUtils.equals(mdv.getMetadataField().getElement(),
"type")) {
return mdv.getValue();
}
}
return null;
}
private RelationshipMetadataValue constructResultingMetadataValue(Item item, String value,
RelationshipMetadataValue metadataValue,
Integer relationshipId) {
metadataValue.setValue(value);
metadataValue.setAuthority(Constants.VIRTUAL_AUTHORITY_PREFIX + relationshipId);
metadataValue.setConfidence(-1);
metadataValue.setDSpaceObject(item);
return metadataValue;
}
//This method will construct a RelationshipMetadataValue object with proper schema, element and qualifier based
//on the key String parameter passed along to it
private RelationshipMetadataValue constructMetadataValue(Context context, String key) {
String[] splittedKey = key.split("\\.");
RelationshipMetadataValue metadataValue = new RelationshipMetadataValue();
String metadataSchema = splittedKey.length > 0 ? splittedKey[0] : null;
String metadataElement = splittedKey.length > 1 ? splittedKey[1] : null;
String metadataQualifier = splittedKey.length > 2 ? splittedKey[2] : null;
MetadataField metadataField = null;
try {
metadataField = metadataFieldService
.findByElement(context, metadataSchema, metadataElement, metadataQualifier);
} catch (SQLException e) {
log.error("Could not find element with MetadataSchema: " + metadataSchema +
", MetadataElement: " + metadataElement + " and MetadataQualifier: " + metadataQualifier, e);
return null;
}
if (metadataField == null) {
log.error("A MetadataValue was attempted to construct with MetadataField for parameters: " +
"metadataschema: {}, metadataelement: {}, metadataqualifier: {}",
metadataSchema, metadataElement, metadataQualifier);
return null;
}
metadataValue.setMetadataField(metadataField);
metadataValue.setLanguage(Item.ANY);
return metadataValue;
}
} }

View File

@@ -77,6 +77,18 @@ public class Relationship implements ReloadableEntity<Integer> {
@Column(name = "right_place") @Column(name = "right_place")
private int rightPlace; private int rightPlace;
/**
* A String containing an alternative value (name variant) for the left side
*/
@Column(name = "leftward_value")
private String leftwardValue;
/**
* A String containing an alternative value (name variant) for the right side
*/
@Column(name = "rightward_value")
private String rightwardValue;
/** /**
* Protected constructor, create object using: * Protected constructor, create object using:
* {@link org.dspace.content.service.RelationshipService#create(Context)} } * {@link org.dspace.content.service.RelationshipService#create(Context)} }
@@ -170,6 +182,38 @@ public class Relationship implements ReloadableEntity<Integer> {
this.rightPlace = rightPlace; this.rightPlace = rightPlace;
} }
/**
* Standard getter for the leftwardValue String in this Relationship
* @return the leftwardValue String for this relationship
*/
public String getLeftwardValue() {
return leftwardValue;
}
/**
* Standard setter for the leftwardValue String in this Relationship
* @param leftwardValue the leftwardValue String that will be used in this relationship
*/
public void setLeftwardValue(String leftwardValue) {
this.leftwardValue = leftwardValue;
}
/**
* Standard getter for the rightwardValue String in this Relationship
* @return the rightwardValue string for this relationship
*/
public String getRightwardValue() {
return rightwardValue;
}
/**
* Standard setter for the rightwardValue String in this Relationship
* @param rightwardValue the rightwardValue String that will be used in this relationship
*/
public void setRightwardValue(String rightwardValue) {
this.rightwardValue = rightwardValue;
}
/** /**
* Standard getter for the ID for this Relationship * Standard getter for the ID for this Relationship
* @return The ID of this relationship * @return The ID of this relationship

View File

@@ -0,0 +1,30 @@
/**
* 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 java.util.List;
import org.dspace.content.virtual.VirtualMetadataPopulator;
/**
* Interface used for the {@link RelationshipMetadataServiceImpl}
* This will define methods regarding the RelationshipMetadata
*/
public interface RelationshipMetadataService {
/**
* This method retrieves a list of MetadataValue objects that get constructed from processing
* the given Item's Relationships through the config given to the {@link VirtualMetadataPopulator}
* @param item The Item that will be processed through it's Relationships
* @param enableVirtualMetadata This parameter will determine whether the list of Relationship metadata
* should be populated with metadata that is being generated through the
* VirtualMetadataPopulator functionality or not
* @return The list of MetadataValue objects constructed through the Relationships
*/
public List<RelationshipMetadataValue> getRelationshipMetadata(Item item, boolean enableVirtualMetadata);
}

View File

@@ -0,0 +1,290 @@
/**
* 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 java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.content.service.MetadataFieldService;
import org.dspace.content.service.RelationshipService;
import org.dspace.content.virtual.VirtualMetadataConfiguration;
import org.dspace.content.virtual.VirtualMetadataPopulator;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
public class RelationshipMetadataServiceImpl implements RelationshipMetadataService {
/**
* log4j category
*/
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger();
@Autowired(required = true)
protected RelationshipService relationshipService;
@Autowired(required = true)
protected VirtualMetadataPopulator virtualMetadataPopulator;
@Autowired(required = true)
protected MetadataFieldService metadataFieldService;
@Override
public List<RelationshipMetadataValue> getRelationshipMetadata(Item item, boolean enableVirtualMetadata) {
Context context = new Context();
List<RelationshipMetadataValue> fullMetadataValueList = new LinkedList<>();
try {
List<MetadataValue> list = item.getMetadata();
String entityType = getEntityTypeStringFromMetadata(list);
if (StringUtils.isNotBlank(entityType)) {
List<Relationship> relationships = relationshipService.findByItem(context, item);
for (Relationship relationship : relationships) {
fullMetadataValueList
.addAll(findRelationshipMetadataValueForItemRelationship(context, item, entityType,
relationship, enableVirtualMetadata));
}
}
} catch (SQLException e) {
log.error("Lookup for Relationships for item with uuid: " + item.getID() + " caused DSpace to crash", e);
}
return fullMetadataValueList;
}
private String getEntityTypeStringFromMetadata(List<MetadataValue> list) {
for (MetadataValue mdv : list) {
if (StringUtils.equals(mdv.getMetadataField().getMetadataSchema().getName(),
"relationship")
&& StringUtils.equals(mdv.getMetadataField().getElement(),
"type")) {
return mdv.getValue();
}
}
return null;
}
/**
* This method processes one Relationship of an Item and will return a list of RelationshipMetadataValue objects
* that are generated for this specific relationship for the item through the config in VirtualMetadataPopulator
*
* It returns a combination of the output of the findVirtualMetadataFromConfiguration method and
*
* @param context The context
* @param item The item whose virtual metadata is requested
* @param entityType The entity type of the given item
* @param relationship The relationship whose virtual metadata is requested
* @param enableVirtualMetadata Determines whether the VirtualMetadataPopulator should be used.
* If false, only the relation."relationname" metadata is populated
* If true, fields from the spring config virtual metadata is included as well
* @return The list of virtual metadata values
*/
private List<RelationshipMetadataValue> findRelationshipMetadataValueForItemRelationship(
Context context, Item item, String entityType, Relationship relationship, boolean enableVirtualMetadata)
throws SQLException {
List<RelationshipMetadataValue> resultingMetadataValueList = new LinkedList<>();
RelationshipType relationshipType = relationship.getRelationshipType();
HashMap<String, VirtualMetadataConfiguration> hashMaps;
String relationName;
Item otherItem;
int place = 0;
boolean isLeftwards;
if (StringUtils.equals(relationshipType.getLeftType().getLabel(), entityType)) {
hashMaps = virtualMetadataPopulator.getMap().get(relationshipType.getLeftwardType());
otherItem = relationship.getRightItem();
relationName = relationship.getRelationshipType().getLeftwardType();
place = relationship.getLeftPlace();
isLeftwards = false; //if the current item is stored on the left,
// the name variant is retrieved from the rightwards label
} else if (StringUtils.equals(relationshipType.getRightType().getLabel(), entityType)) {
hashMaps = virtualMetadataPopulator.getMap().get(relationshipType.getRightwardType());
otherItem = relationship.getLeftItem();
relationName = relationship.getRelationshipType().getRightwardType();
place = relationship.getRightPlace();
isLeftwards = true; //if the current item is stored on the right,
// the name variant is retrieved from the leftwards label
} else {
//No virtual metadata can be created
return resultingMetadataValueList;
}
if (hashMaps != null && enableVirtualMetadata) {
resultingMetadataValueList.addAll(findVirtualMetadataFromConfiguration(context, item, hashMaps,
otherItem, relationName,
relationship, place, isLeftwards));
}
RelationshipMetadataValue relationMetadataFromOtherItem =
getRelationMetadataFromOtherItem(context, otherItem, relationName, relationship.getID(), place);
if (relationMetadataFromOtherItem != null) {
resultingMetadataValueList.add(relationMetadataFromOtherItem);
}
return resultingMetadataValueList;
}
/**
* This method will retrieve a list of RelationshipMetadataValue objects based on the config passed along in the
* hashmaps parameter. The beans will be used to retrieve the values for the RelationshipMetadataValue objects
* and the keys of the hashmap will be used to construct the RelationshipMetadataValue object.
*
* @param context The context
* @param item The item whose virtual metadata is requested
* @param hashMaps The list of VirtualMetadataConfiguration objects which will generate the
* virtual metadata. These configurations are applicable for a relationship
* between both items
* @param otherItem The related item whose actual metadata is requested
* @param relationName The name of the relationship
* @param relationship The relationship whose virtual metadata is requested
* @param place The place to use in the virtual metadata
* @param isLeftwards Determines the direction of the virtual metadata
* @return The list of virtual metadata values
*/
private List<RelationshipMetadataValue> findVirtualMetadataFromConfiguration(Context context, Item item,
HashMap<String, VirtualMetadataConfiguration> hashMaps, Item otherItem, String relationName,
Relationship relationship, int place, boolean isLeftwards) throws SQLException {
List<RelationshipMetadataValue> resultingMetadataValueList = new LinkedList<>();
for (Map.Entry<String, VirtualMetadataConfiguration> entry : hashMaps.entrySet()) {
String key = entry.getKey();
VirtualMetadataConfiguration virtualBean = entry.getValue();
if (virtualBean.getPopulateWithNameVariant()) {
String wardLabel = isLeftwards ? relationship.getLeftwardValue() : relationship.getRightwardValue();
if (wardLabel != null) {
resultingMetadataValueList.add(
constructRelationshipMetadataValue(context, item, relationship.getID(), place, key, virtualBean,
wardLabel));
} else {
resultingMetadataValueList.addAll(
findRelationshipMetadataValueFromBean(context, item, otherItem, relationship, place, key,
virtualBean));
}
} else {
resultingMetadataValueList.addAll(
findRelationshipMetadataValueFromBean(context, item, otherItem, relationship, place, key,
virtualBean));
}
}
return resultingMetadataValueList;
}
/**
* This method will retrieve a list of RelationshipMetadataValue objects based on the config passed along in the
* hashmaps parameter. The beans will be used to retrieve the values for the RelationshipMetadataValue objects
* and the keys of the hashmap will be used to construct the RelationshipMetadataValue object.
*
* @param context The context
* @param item The item whose virtual metadata is requested
* @param otherItem The related item whose actual metadata is requested
* @param relationship The relationship whose virtual metadata is requested
* @param place The place to use in the virtual metadata
* @param key The key corresponding to the VirtualMetadataConfiguration
* @param virtualBean The VirtualMetadataConfiguration object which will generate the
* virtual metadata. This configuration is applicable for a relationship
* between both items
* @return The list of virtual metadata values
*/
private List<RelationshipMetadataValue> findRelationshipMetadataValueFromBean(
Context context, Item item, Item otherItem, Relationship relationship, int place,
String key, VirtualMetadataConfiguration virtualBean) throws SQLException {
List<RelationshipMetadataValue> resultingMetadataValueList = new LinkedList<>();
for (String value : virtualBean.getValues(context, otherItem)) {
RelationshipMetadataValue relationshipMetadataValue = constructRelationshipMetadataValue(context, item,
relationship
.getID(),
place,
key, virtualBean,
value);
if (relationshipMetadataValue != null) {
resultingMetadataValueList.add(relationshipMetadataValue);
}
}
return resultingMetadataValueList;
}
//This method will construct a RelationshipMetadataValue object with proper schema, element, qualifier,
//authority, item, place and useForPlace based on the key String parameter passed along to it
private RelationshipMetadataValue constructRelationshipMetadataValue(Context context, Item item,
Integer relationshipId, int place,
String key,
VirtualMetadataConfiguration virtualBean,
String value) {
RelationshipMetadataValue metadataValue = constructMetadataValue(context, key);
if (metadataValue != null) {
metadataValue = constructResultingMetadataValue(item, value, metadataValue, relationshipId);
metadataValue.setUseForPlace(virtualBean.getUseForPlace());
metadataValue.setPlace(place);
if (StringUtils.isNotBlank(metadataValue.getValue())) {
return metadataValue;
}
}
return null;
}
//This method will construct a RelationshipMetadataValue object with proper schema, element and qualifier based
//on the key String parameter passed along to it
private RelationshipMetadataValue constructMetadataValue(Context context, String key) {
String[] splittedKey = key.split("\\.");
RelationshipMetadataValue metadataValue = new RelationshipMetadataValue();
String metadataSchema = splittedKey.length > 0 ? splittedKey[0] : null;
String metadataElement = splittedKey.length > 1 ? splittedKey[1] : null;
String metadataQualifier = splittedKey.length > 2 ? splittedKey[2] : null;
MetadataField metadataField = null;
try {
metadataField = metadataFieldService
.findByElement(context, metadataSchema, metadataElement, metadataQualifier);
} catch (SQLException e) {
log.error("Could not find element with MetadataSchema: " + metadataSchema +
", MetadataElement: " + metadataElement + " and MetadataQualifier: " + metadataQualifier, e);
return null;
}
if (metadataField == null) {
log.error("A MetadataValue was attempted to construct with MetadataField for parameters: " +
"metadataschema: {}, metadataelement: {}, metadataqualifier: {}",
metadataSchema, metadataElement, metadataQualifier);
return null;
}
metadataValue.setMetadataField(metadataField);
metadataValue.setLanguage(Item.ANY);
return metadataValue;
}
//This method will update a RelationshipMetadataValue object with authority info and relation to the item
private RelationshipMetadataValue constructResultingMetadataValue(Item item, String value,
RelationshipMetadataValue metadataValue,
Integer relationshipId) {
metadataValue.setValue(value);
metadataValue.setAuthority(Constants.VIRTUAL_AUTHORITY_PREFIX + relationshipId);
metadataValue.setConfidence(-1);
metadataValue.setDSpaceObject(item);
return metadataValue;
}
// This method will create the Relationship Metadatavalue that describes the relationship type and has the ID
// of the other item as value
private RelationshipMetadataValue getRelationMetadataFromOtherItem(Context context, Item otherItem,
String relationName,
Integer relationshipId, int place) {
RelationshipMetadataValue metadataValue = constructMetadataValue(context,
MetadataSchemaEnum.RELATION
.getName() + "." + relationName);
if (metadataValue != null) {
metadataValue.setAuthority(Constants.VIRTUAL_AUTHORITY_PREFIX + relationshipId);
metadataValue.setValue(otherItem.getID().toString());
metadataValue.setPlace(place);
return metadataValue;
}
return null;
}
}

View File

@@ -10,7 +10,6 @@ package org.dspace.content;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
@@ -59,12 +58,21 @@ public class RelationshipServiceImpl implements RelationshipService {
@Override @Override
public Relationship create(Context c, Item leftItem, Item rightItem, RelationshipType relationshipType, public Relationship create(Context c, Item leftItem, Item rightItem, RelationshipType relationshipType,
int leftPlace, int rightPlace) throws AuthorizeException, SQLException { int leftPlace, int rightPlace) throws AuthorizeException, SQLException {
return create(c, leftItem, rightItem, relationshipType, leftPlace, rightPlace, null, null);
}
@Override
public Relationship create(Context c, Item leftItem, Item rightItem, RelationshipType relationshipType,
int leftPlace, int rightPlace, String leftwardValue, String rightwardValue)
throws AuthorizeException, SQLException {
Relationship relationship = new Relationship(); Relationship relationship = new Relationship();
relationship.setLeftItem(leftItem); relationship.setLeftItem(leftItem);
relationship.setRightItem(rightItem); relationship.setRightItem(rightItem);
relationship.setRelationshipType(relationshipType); relationship.setRelationshipType(relationshipType);
relationship.setLeftPlace(leftPlace); relationship.setLeftPlace(leftPlace);
relationship.setRightPlace(rightPlace); relationship.setRightPlace(rightPlace);
relationship.setLeftwardValue(leftwardValue);
relationship.setRightwardValue(rightwardValue);
return create(c, relationship); return create(c, relationship);
} }
@@ -99,7 +107,7 @@ public class RelationshipServiceImpl implements RelationshipService {
false); false);
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
//If useForPlace for the leftlabel is false for the relationshipType, //If useForPlace for the leftwardType is false for the relationshipType,
// we need to sort the relationships here based on leftplace. // we need to sort the relationships here based on leftplace.
if (!virtualMetadataPopulator.isUseForPlaceTrueForRelationshipType(relationship.getRelationshipType(), true)) { if (!virtualMetadataPopulator.isUseForPlaceTrueForRelationshipType(relationship.getRelationshipType(), true)) {
if (!leftRelationships.isEmpty()) { if (!leftRelationships.isEmpty()) {
@@ -116,7 +124,7 @@ public class RelationshipServiceImpl implements RelationshipService {
} }
//If useForPlace for the rightLabel is false for the relationshipType, //If useForPlace for the rightwardType is false for the relationshipType,
// we need to sort the relationships here based on the rightplace. // we need to sort the relationships here based on the rightplace.
if (!virtualMetadataPopulator.isUseForPlaceTrueForRelationshipType(relationship.getRelationshipType(), false)) { if (!virtualMetadataPopulator.isUseForPlaceTrueForRelationshipType(relationship.getRelationshipType(), false)) {
if (!rightRelationships.isEmpty()) { if (!rightRelationships.isEmpty()) {
@@ -221,8 +229,8 @@ public class RelationshipServiceImpl implements RelationshipService {
private void logRelationshipTypeDetailsForError(RelationshipType relationshipType) { private void logRelationshipTypeDetailsForError(RelationshipType relationshipType) {
log.warn("The relationshipType's ID is: " + relationshipType.getID()); log.warn("The relationshipType's ID is: " + relationshipType.getID());
log.warn("The relationshipType's left label is: " + relationshipType.getLeftLabel()); log.warn("The relationshipType's leftward type is: " + relationshipType.getLeftwardType());
log.warn("The relationshipType's right label is: " + relationshipType.getRightLabel()); log.warn("The relationshipType's rightward type is: " + relationshipType.getRightwardType());
log.warn("The relationshipType's left entityType label is: " + relationshipType.getLeftType().getLabel()); log.warn("The relationshipType's left entityType label is: " + relationshipType.getLeftType().getLabel());
log.warn("The relationshipType's right entityType label is: " + relationshipType.getRightType().getLabel()); log.warn("The relationshipType's right entityType label is: " + relationshipType.getRightType().getLabel());
log.warn("The relationshipType's left min cardinality is: " + relationshipType.getLeftMinCardinality()); log.warn("The relationshipType's left min cardinality is: " + relationshipType.getLeftMinCardinality());
@@ -259,11 +267,18 @@ public class RelationshipServiceImpl implements RelationshipService {
@Override @Override
public List<Relationship> findByItem(Context context, Item item) throws SQLException { public List<Relationship> findByItem(Context context, Item item) throws SQLException {
List<Relationship> list = relationshipDAO.findByItem(context, item); return findByItem(context, item, -1, -1);
}
@Override
public List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset)
throws SQLException {
List<Relationship> list = relationshipDAO.findByItem(context, item, limit, offset);
list.sort((o1, o2) -> { list.sort((o1, o2) -> {
int relationshipType = o1.getRelationshipType().getLeftLabel() int relationshipType = o1.getRelationshipType().getLeftwardType()
.compareTo(o2.getRelationshipType().getLeftLabel()); .compareTo(o2.getRelationshipType().getLeftwardType());
if (relationshipType != 0) { if (relationshipType != 0) {
return relationshipType; return relationshipType;
} else { } else {
@@ -279,7 +294,12 @@ public class RelationshipServiceImpl implements RelationshipService {
@Override @Override
public List<Relationship> findAll(Context context) throws SQLException { public List<Relationship> findAll(Context context) throws SQLException {
return relationshipDAO.findAll(context, Relationship.class); return findAll(context, -1, -1);
}
@Override
public List<Relationship> findAll(Context context, Integer limit, Integer offset) throws SQLException {
return relationshipDAO.findAll(context, Relationship.class, limit, offset);
} }
@Override @Override
@@ -359,8 +379,8 @@ public class RelationshipServiceImpl implements RelationshipService {
private boolean checkMinCardinality(Context context, Item item, private boolean checkMinCardinality(Context context, Item item,
Relationship relationship, Relationship relationship,
Integer minCardinality, boolean isLeft) throws SQLException { Integer minCardinality, boolean isLeft) throws SQLException {
List<Relationship> list = this List<Relationship> list = this.findByItemAndRelationshipType(context, item, relationship.getRelationshipType(),
.findByItemAndRelationshipType(context, item, relationship.getRelationshipType(), isLeft); isLeft, -1, -1);
if (minCardinality != null && !(list.size() > minCardinality)) { if (minCardinality != null && !(list.size() > minCardinality)) {
return false; return false;
} }
@@ -369,46 +389,83 @@ public class RelationshipServiceImpl implements RelationshipService {
public List<Relationship> findByItemAndRelationshipType(Context context, Item item, public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType, boolean isLeft) RelationshipType relationshipType, boolean isLeft)
throws SQLException { throws SQLException {
List<Relationship> list = this.findByItem(context, item); return this.findByItemAndRelationshipType(context, item, relationshipType, isLeft, -1, -1);
List<Relationship> listToReturn = new LinkedList<>();
for (Relationship relationship : list) {
if (isLeft) {
if (StringUtils
.equals(relationship.getRelationshipType().getLeftLabel(), relationshipType.getLeftLabel())) {
listToReturn.add(relationship);
}
} else {
if (StringUtils
.equals(relationship.getRelationshipType().getRightLabel(), relationshipType.getRightLabel())) {
listToReturn.add(relationship);
}
}
}
return listToReturn;
} }
@Override @Override
public List<Relationship> findByItemAndRelationshipType(Context context, Item item, public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType) RelationshipType relationshipType)
throws SQLException { throws SQLException {
List<Relationship> list = this.findByItem(context, item); return relationshipDAO.findByItemAndRelationshipType(context, item, relationshipType, -1, -1);
List<Relationship> listToReturn = new LinkedList<>(); }
for (Relationship relationship : list) {
if (relationship.getRelationshipType().equals(relationshipType)) { @Override
listToReturn.add(relationship); public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
} RelationshipType relationshipType, int limit, int offset)
} throws SQLException {
return listToReturn; return relationshipDAO.findByItemAndRelationshipType(context, item, relationshipType, limit, offset);
}
@Override
public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType, boolean isLeft,
int limit, int offset)
throws SQLException {
return relationshipDAO.findByItemAndRelationshipType(context, item, relationshipType, isLeft, limit, offset);
} }
@Override @Override
public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType) public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType)
throws SQLException { throws SQLException {
return relationshipDAO.findByRelationshipType(context, relationshipType);
return findByRelationshipType(context, relationshipType, -1, -1);
}
@Override
public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType, Integer limit,
Integer offset)
throws SQLException {
return relationshipDAO.findByRelationshipType(context, relationshipType, limit, offset);
}
@Override
public List<Relationship> findByTypeName(Context context, String typeName)
throws SQLException {
return this.findByTypeName(context, typeName, -1, -1);
}
@Override
public List<Relationship> findByTypeName(Context context, String typeName, Integer limit, Integer offset)
throws SQLException {
return relationshipDAO.findByTypeName(context, typeName, limit, offset);
} }
@Override
public int countTotal(Context context) throws SQLException {
return relationshipDAO.countRows(context);
}
@Override
public int countByItem(Context context, Item item) throws SQLException {
return relationshipDAO.countByItem(context, item);
}
@Override
public int countByRelationshipType(Context context, RelationshipType relationshipType) throws SQLException {
return relationshipDAO.countByRelationshipType(context, relationshipType);
}
@Override
public int countByItemAndRelationshipType(Context context, Item item, RelationshipType relationshipType)
throws SQLException {
return relationshipDAO.countByItemAndRelationshipType(context, item, relationshipType);
}
@Override
public int countByTypeName(Context context, String typeName)
throws SQLException {
return relationshipDAO.countByTypeName(context, typeName);
}
} }

View File

@@ -26,8 +26,8 @@ import org.dspace.core.ReloadableEntity;
* Class representing a RelationshipType * Class representing a RelationshipType
* This class contains an Integer ID that will be the unique value and primary key in the database. * This class contains an Integer ID that will be the unique value and primary key in the database.
* This key is automatically generated * This key is automatically generated
* It also has a leftType and rightType EntityType that describes the relationshipType together with a leftLabel and * It also has a leftType and rightType EntityType that describes the relationshipType together with a leftwardType and
* rightLabel. * rightwardType.
* The cardinality properties describe how many of each relations this relationshipType can support * The cardinality properties describe how many of each relations this relationshipType can support
*/ */
@Entity @Entity
@@ -61,20 +61,20 @@ public class RelationshipType implements ReloadableEntity<Integer> {
private EntityType rightType; private EntityType rightType;
/** /**
* The leftLabel String field for the relationshipType * The leftwardType String field for the relationshipType
* This is stored as a String and cannot be null * This is stored as a String and cannot be null
* This is a textual representation of the name of the relationship that this RelationshipType is connected to * This is a textual representation of the name of the relationship that this RelationshipType is connected to
*/ */
@Column(name = "left_label", nullable = false) @Column(name = "leftward_type", nullable = false)
private String leftLabel; private String leftwardType;
/** /**
* The rightLabel String field for the relationshipType * The rightwardType String field for the relationshipType
* This is stored as a String and cannot be null * This is stored as a String and cannot be null
* This is a textual representation of the name of the relationship that this RelationshipType is connected to * This is a textual representation of the name of the relationship that this RelationshipType is connected to
*/ */
@Column(name = "right_label", nullable = false) @Column(name = "rightward_type", nullable = false)
private String rightLabel; private String rightwardType;
/** /**
* The minimum amount of relations for the leftItem that need to be present at all times * The minimum amount of relations for the leftItem that need to be present at all times
@@ -149,35 +149,35 @@ public class RelationshipType implements ReloadableEntity<Integer> {
} }
/** /**
* Standard getter for the leftLabel String for this RelationshipType * Standard getter for the leftwardType String for this RelationshipType
* @return The leftLabel String of this RelationshipType * @return The leftwardType String of this RelationshipType
*/ */
public String getLeftLabel() { public String getLeftwardType() {
return leftLabel; return leftwardType;
} }
/** /**
* Standard setter for the leftLabel String for this RelationshipType * Standard setter for the leftwardType String for this RelationshipType
* @param leftLabel The leftLabel String that this RelationshipType should receive * @param leftwardType The leftwardType String that this RelationshipType should receive
*/ */
public void setLeftLabel(String leftLabel) { public void setLeftwardType(String leftwardType) {
this.leftLabel = leftLabel; this.leftwardType = leftwardType;
} }
/** /**
* Standard getter for the rightLabel String for this RelationshipType * Standard getter for the rightwardType String for this RelationshipType
* @return The rightLabel String of this RelationshipType * @return The rightwardType String of this RelationshipType
*/ */
public String getRightLabel() { public String getRightwardType() {
return rightLabel; return rightwardType;
} }
/** /**
* Standard setter for the rightLabel String for this RelationshipType * Standard setter for the rightwardType String for this RelationshipType
* @param rightLabel The rightLabel String that this RelationshipType should receive * @param rightwardType The rightwardType String that this RelationshipType should receive
*/ */
public void setRightLabel(String rightLabel) { public void setRightwardType(String rightwardType) {
this.rightLabel = rightLabel; this.rightwardType = rightwardType;
} }
/** /**

View File

@@ -47,37 +47,69 @@ public class RelationshipTypeServiceImpl implements RelationshipTypeService {
} }
@Override @Override
public RelationshipType findbyTypesAndLabels(Context context,EntityType leftType,EntityType rightType, public RelationshipType findbyTypesAndTypeName(Context context,EntityType leftType,EntityType rightType,
String leftLabel,String rightLabel) throws SQLException { String leftwardType,String rightwardType) throws SQLException {
return relationshipTypeDAO.findByTypesAndLabels(context, leftType, rightType, leftLabel, rightLabel); return relationshipTypeDAO.findbyTypesAndTypeName(context, leftType, rightType, leftwardType, rightwardType);
} }
@Override @Override
public List<RelationshipType> findAll(Context context) throws SQLException { public List<RelationshipType> findAll(Context context) throws SQLException {
return relationshipTypeDAO.findAll(context, RelationshipType.class); return findAll(context, -1, -1);
} }
@Override @Override
public List<RelationshipType> findByLeftOrRightLabel(Context context, String label) throws SQLException { public List<RelationshipType> findAll(Context context, Integer limit, Integer offset) throws SQLException {
return relationshipTypeDAO.findByLeftOrRightLabel(context, label);
return relationshipTypeDAO.findAll(context, RelationshipType.class, limit, offset);
}
@Override
public List<RelationshipType> findByLeftwardOrRightwardTypeName(Context context, String typeName)
throws SQLException {
return findByLeftwardOrRightwardTypeName(context, typeName, -1, -1);
}
@Override
public List<RelationshipType> findByLeftwardOrRightwardTypeName(Context context, String typeName, Integer limit,
Integer offset)
throws SQLException {
return relationshipTypeDAO.findByLeftwardOrRightwardTypeName(context, typeName, limit, offset);
} }
@Override @Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException { public List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException {
return relationshipTypeDAO.findByEntityType(context, entityType); return findByEntityType(context, entityType, -1, -1);
}
@Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType,
Integer limit, Integer offset) throws SQLException {
return relationshipTypeDAO.findByEntityType(context, entityType, limit, offset);
}
@Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType, boolean isLeft)
throws SQLException {
return findByEntityType(context, entityType, isLeft, -1, -1);
}
@Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType, boolean isLeft,
Integer limit, Integer offset) throws SQLException {
return relationshipTypeDAO.findByEntityType(context, entityType, isLeft, limit, offset);
} }
@Override @Override
public RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType, public RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType,
String leftLabel, String rightLabel, Integer leftCardinalityMinInteger, String leftwardType, String rightwardType, Integer leftCardinalityMinInteger,
Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger, Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger,
Integer rightCardinalityMaxInteger) Integer rightCardinalityMaxInteger)
throws SQLException, AuthorizeException { throws SQLException, AuthorizeException {
RelationshipType relationshipType = new RelationshipType(); RelationshipType relationshipType = new RelationshipType();
relationshipType.setLeftType(leftEntityType); relationshipType.setLeftType(leftEntityType);
relationshipType.setRightType(rightEntityType); relationshipType.setRightType(rightEntityType);
relationshipType.setLeftLabel(leftLabel); relationshipType.setLeftwardType(leftwardType);
relationshipType.setRightLabel(rightLabel); relationshipType.setRightwardType(rightwardType);
relationshipType.setLeftMinCardinality(leftCardinalityMinInteger); relationshipType.setLeftMinCardinality(leftCardinalityMinInteger);
relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger); relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger);
relationshipType.setRightMinCardinality(rightCardinalityMinInteger); relationshipType.setRightMinCardinality(rightCardinalityMinInteger);

View File

@@ -220,6 +220,11 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
return controller; return controller;
} }
@Override
public void clearCache() {
controller.clear();
authorities.clear();
}
private void loadChoiceAuthorityConfigurations() { private void loadChoiceAuthorityConfigurations() {
// Get all configuration keys starting with a given prefix // Get all configuration keys starting with a given prefix
List<String> propKeys = configurationService.getPropertyKeys(CHOICES_PLUGIN_PREFIX); List<String> propKeys = configurationService.getPropertyKeys(CHOICES_PLUGIN_PREFIX);

View File

@@ -241,7 +241,7 @@ public class DSpaceControlledVocabulary extends SelfNamedPlugin implements Choic
} catch (XPathExpressionException e) { } catch (XPathExpressionException e) {
log.warn(e.getMessage(), e); log.warn(e.getMessage(), e);
} }
return new Choice("", "", ""); return null;
} }
private void readNode(String[] authorities, String[] values, String[] labels, String[] parent, String[] notes, private void readNode(String[] authorities, String[] values, String[] labels, String[] parent, String[] notes,

View File

@@ -65,7 +65,7 @@ public class InputFormSelfRegisterWrapperAuthority implements ChoiceAuthority {
} }
} }
if (!choices.isEmpty()) { if (!choices.isEmpty()) {
Choice[] results = new Choice[choices.size() - 1]; Choice[] results = new Choice[choices.size()];
choices.toArray(results); choices.toArray(results);
return new Choices(results, 0, choices.size(), Choices.CF_AMBIGUOUS, false); return new Choices(results, 0, choices.size(), Choices.CF_AMBIGUOUS, false);
} }

View File

@@ -188,8 +188,8 @@ public class SolrAuthority implements ChoiceAuthority {
} }
private String toQuery(String searchField, String text) { private String toQuery(String searchField, String text) {
return searchField + ":\"" + text.toLowerCase().replaceAll(":", "\\:") + "*\" or " + searchField + ":\"" + text return searchField + ":(" + text.toLowerCase().replaceAll(":", "\\:") + "*) or " + searchField + ":(" + text
.toLowerCase().replaceAll(":", "\\:") + "\""; .toLowerCase().replaceAll(":", "\\:") + ")";
} }
@Override @Override

View File

@@ -168,4 +168,9 @@ public interface ChoiceAuthorityService {
public ChoiceAuthority getChoiceAuthorityByAuthorityName(String authorityName); public ChoiceAuthority getChoiceAuthorityByAuthorityName(String authorityName);
/**
* This method has been created to have a way of clearing the cache kept inside the service
*/
public void clearCache();
} }

View File

@@ -34,7 +34,21 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
* right item that is equal to the given item * right item that is equal to the given item
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
List<Relationship> findByItem(Context context,Item item) throws SQLException; List<Relationship> findByItem(Context context, Item item) throws SQLException;
/**
* This method returns a list of Relationship objects that have the given Item object
* as a leftItem or a rightItem
* @param context The relevant DSpace context
* @param item The item that should be either a leftItem or a rightItem of all
* the Relationship objects in the returned list
* @param limit paging limit
* @param offset paging offset
* @return The list of Relationship objects that contain either a left or a
* right item that is equal to the given item
* @throws SQLException If something goes wrong
*/
List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset) throws SQLException;
/** /**
* This method returns the highest leftplace integer for all the relationships where this * This method returns the highest leftplace integer for all the relationships where this
@@ -45,7 +59,7 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
* that have the given item as leftItem * that have the given item as leftItem
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
int findLeftPlaceByLeftItem(Context context,Item item) throws SQLException; int findLeftPlaceByLeftItem(Context context, Item item) throws SQLException;
/** /**
* This method returns the highest rightplace integer for all the relationships where this * This method returns the highest rightplace integer for all the relationships where this
@@ -56,7 +70,7 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
* that have the given item as rightItem * that have the given item as rightItem
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
int findRightPlaceByRightItem(Context context,Item item) throws SQLException; int findRightPlaceByRightItem(Context context, Item item) throws SQLException;
/** /**
* This method returns a list of Relationship objects for the given RelationshipType object. * This method returns a list of Relationship objects for the given RelationshipType object.
@@ -69,4 +83,132 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType) throws SQLException; List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType) 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
* @param limit paging limit
* @param offset paging offset
* @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,
Integer limit, Integer offset) 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
* @param limit paging limit
* @param offset paging offset
* @param item item to filter by
* @return A list of Relationship objects that have the given RelationshipType object as the
* relationshipType property
* @throws SQLException If something goes wrong
*/
List<Relationship> findByItemAndRelationshipType(Context context, Item item, RelationshipType relationshipType,
Integer limit, Integer offset) 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
* @param limit paging limit
* @param offset paging offset
* @param item item to filter by
* @param isLeft Is item left or right
* @return A list of Relationship objects that have the given RelationshipType object as the
* relationshipType property
* @throws SQLException If something goes wrong
*/
List<Relationship> findByItemAndRelationshipType(Context context, Item item, RelationshipType relationshipType,
boolean isLeft, Integer limit, Integer offset)
throws SQLException;
/**
* This method returns a list of Relationship objects for the given typeName
* @param context The relevant DSpace context
* @param typeName The leftward or rightward typeName of the relationship type
* @return A list of Relationship objects that have the given RelationshipType object as the
* relationshipType property
* @throws SQLException If something goes wrong
*/
List<Relationship> findByTypeName(Context context, String typeName)
throws SQLException;
/**
* This method returns a list of Relationship objects for the given typeName
* @param context The relevant DSpace context
* @param typeName The leftward or rightward typeName of the relationship type
* @param limit paging limit
* @param offset paging offset
* @return A list of Relationship objects that have the given RelationshipType object as the
* relationshipType property
* @throws SQLException If something goes wrong
*/
List<Relationship> findByTypeName(Context context, String typeName, Integer limit, Integer offset)
throws SQLException;
/**
* Count total number of relationships (rows in relationship table)
*
* @param context context
* @return total count
* @throws SQLException if database error
*/
int countRows(Context context) throws SQLException;
/**
* Count total number of relationships (rows in relationship table) by a relationship type
*
* @param context context
* @param relationshipType relationship type to filter by
* @return total count
* @throws SQLException if database error
*/
int countByRelationshipType(Context context, RelationshipType relationshipType) throws SQLException;
/**
* This method returns a count of Relationship objects that have the given Item object
* as a leftItem or a rightItem
* @param context The relevant DSpace context
* @param item The item that should be either a leftItem or a rightItem of all
* the Relationship objects in the returned list
* @return The list of Relationship objects that contain either a left or a
* right item that is equal to the given item
* @throws SQLException If something goes wrong
*/
int countByItem(Context context, Item item) throws SQLException;
/**
* Count total number of relationships (rows in relationship table) by an item and a relationship type
*
* @param context context
* @param relationshipType relationship type to filter by
* @param item item to filter by
* @return total count
* @throws SQLException if database error
*/
int countByItemAndRelationshipType(Context context, Item item, RelationshipType relationshipType)
throws SQLException;
/**
* Count total number of relationships (rows in relationship table) given a typeName
*
* @param context context
* @param typeName the relationship typeName to filter by
* @return total count
* @throws SQLException if database error
*/
int countByTypeName(Context context, String typeName)
throws SQLException;
} }

View File

@@ -25,28 +25,44 @@ public interface RelationshipTypeDAO extends GenericDAO<RelationshipType> {
/** /**
* This method is used to retrieve the RelationshipType object that has the same * This method is used to retrieve the RelationshipType object that has the same
* leftType, rightType, leftLabel and rightLabel as given in the parameters * leftType, rightType, leftwardType and rightwardType as given in the parameters
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param leftType The leftType EntityType object to be matched in the query * @param leftType The leftType EntityType object to be matched in the query
* @param rightType The rightType EntityType object to be matched in the query * @param rightType The rightType EntityType object to be matched in the query
* @param leftLabel The leftLabel String to be matched in the query * @param leftwardType The leftwardType String to be matched in the query
* @param rightLabel The rightLabel String to be matched in the query * @param rightwardType The rightwardType String to be matched in the query
* @return The RelationshipType object that matches all the given parameters * @return The RelationshipType object that matches all the given parameters
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
RelationshipType findByTypesAndLabels(Context context, RelationshipType findbyTypesAndTypeName(Context context, EntityType leftType,EntityType rightType,
EntityType leftType,EntityType rightType,String leftLabel,String rightLabel) String leftwardType,
throws SQLException; String rightwardType)
throws SQLException;
/**
* This method will return a list of RelationshipType objects for which the given label is equal to
* either the leftwardType or rightwardType.
* @param context The relevant DSpace context
* @param type The label that will be used to check on
* @return A list of RelationshipType objects that have the given label as either the leftwardType
* or rightwardType
* @throws SQLException If something goes wrong
*/
List<RelationshipType> findByLeftwardOrRightwardTypeName(Context context, String type) throws SQLException;
/** /**
* This method will return a list of RelationshipType objects for which the given label is equal to * This method will return a list of RelationshipType objects for which the given label is equal to
* either the leftLabel or rightLabel. * either the leftLabel or rightLabel.
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param label The label that will be used to check on * @param type The label that will be used to check on
* @param limit paging limit
* @param offset paging offset
* @return A list of RelationshipType objects that have the given label as either the leftLabel or rightLabel * @return A list of RelationshipType objects that have the given label as either the leftLabel or rightLabel
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
List<RelationshipType> findByLeftOrRightLabel(Context context, String label) throws SQLException; List<RelationshipType> findByLeftwardOrRightwardTypeName(Context context, String type, Integer limit,
Integer offset)
throws SQLException;
/** /**
* This method will return a list of RelationshipType objects for which the given EntityType object is equal * This method will return a list of RelationshipType objects for which the given EntityType object is equal
@@ -58,4 +74,50 @@ public interface RelationshipTypeDAO extends GenericDAO<RelationshipType> {
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException; List<RelationshipType> findByEntityType(Context context, EntityType entityType) 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
* @param limit paging limit
* @param offset paging offset
* @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, Integer limit, Integer offset)
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
* @param isLeft Boolean value used to filter by left_type or right_type. If true left_type results only
* else right_type results.
* @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, Boolean isLeft)
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
* @param isLeft Boolean value used to filter by left_type or right_type. If true left_type results only
* else right_type results.
* @param limit paging limit
* @param offset paging offset
* @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, Boolean isLeft,
Integer limit, Integer offset)
throws SQLException;
} }

View File

@@ -8,8 +8,6 @@
package org.dspace.content.dao.impl; package org.dspace.content.dao.impl;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import javax.persistence.Query; import javax.persistence.Query;
@@ -62,11 +60,20 @@ public class CommunityDAOImpl extends AbstractHibernateDSODAO<Community> impleme
public List<Community> findAll(Context context, MetadataField sortField, Integer limit, Integer offset) public List<Community> findAll(Context context, MetadataField sortField, Integer limit, Integer offset)
throws SQLException { throws SQLException {
StringBuilder queryBuilder = new StringBuilder(); StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("SELECT ").append(Community.class.getSimpleName()).append(" FROM Community as ")
.append(Community.class.getSimpleName()).append(" ");
addMetadataLeftJoin(queryBuilder, Community.class.getSimpleName(), Arrays.asList(sortField));
addMetadataSortQuery(queryBuilder, Arrays.asList(sortField), Collections.EMPTY_LIST);
// The query has to be rather complex because we want to sort the retrieval of Communities based on the title
// We'll join the Communities with the metadata fields on the sortfield specified in the parameters
// then we'll sort on this metadata field (this is usually the title). We're also making sure that the place
// is the lowest place in the metadata fields list so that we avoid the duplication bug
queryBuilder.append("SELECT c" +
" FROM Community c" +
" left join c.metadata title on title.metadataField = :sortField and" +
" title.dSpaceObject = c.id and" +
" title.place = (select min(internal.place) " +
"from c.metadata internal " +
"where internal.metadataField = :sortField and" +
" internal.dSpaceObject = c.id)" +
" ORDER BY LOWER(title.value)");
Query query = createQuery(context, queryBuilder.toString()); Query query = createQuery(context, queryBuilder.toString());
if (offset != null) { if (offset != null) {
query.setFirstResult(offset); query.setFirstResult(offset);
@@ -74,7 +81,8 @@ public class CommunityDAOImpl extends AbstractHibernateDSODAO<Community> impleme
if (limit != null) { if (limit != null) {
query.setMaxResults(limit); query.setMaxResults(limit);
} }
query.setParameter(sortField.toString(), sortField.getID()); query.setParameter("sortField", sortField);
return list(query); return list(query);
} }
@@ -91,16 +99,26 @@ public class CommunityDAOImpl extends AbstractHibernateDSODAO<Community> impleme
@Override @Override
public List<Community> findAllNoParent(Context context, MetadataField sortField) throws SQLException { public List<Community> findAllNoParent(Context context, MetadataField sortField) throws SQLException {
StringBuilder queryBuilder = new StringBuilder(); StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("SELECT community FROM Community as community ");
addMetadataLeftJoin(queryBuilder, Community.class.getSimpleName().toLowerCase(), Arrays.asList(sortField));
addMetadataValueWhereQuery(queryBuilder, Collections.EMPTY_LIST, null, " community.parentCommunities IS EMPTY");
addMetadataSortQuery(queryBuilder, Arrays.asList(sortField), Collections.EMPTY_LIST);
// The query has to be rather complex because we want to sort the retrieval of Communities based on the title
// We'll join the Communities with the metadata fields on the sortfield specified in the parameters
// then we'll sort on this metadata field (this is usually the title). We're also making sure that the place
// is the lowest place in the metadata fields list so that we avoid the duplication bug
// This query has the added where clause to enforce that the community cannot have any parent communities
queryBuilder.append("SELECT c" +
" FROM Community c" +
" left join c.metadata title on title.metadataField = :sortField and" +
" title.dSpaceObject = c.id and" +
" title.place = (select min(internal.place) " +
"from c.metadata internal " +
"where internal.metadataField = :sortField and" +
" internal.dSpaceObject = c.id)" +
" WHERE c.parentCommunities IS EMPTY " +
" ORDER BY LOWER(title.value)");
Query query = createQuery(context, queryBuilder.toString()); Query query = createQuery(context, queryBuilder.toString());
query.setParameter(sortField.toString(), sortField.getID()); query.setParameter("sortField", sortField);
query.setHint("org.hibernate.cacheable", Boolean.TRUE); query.setHint("org.hibernate.cacheable", Boolean.TRUE);
return findMany(context, query); return findMany(context, query);
} }

View File

@@ -8,6 +8,7 @@
package org.dspace.content.dao.impl; package org.dspace.content.dao.impl;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
@@ -18,6 +19,8 @@ import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType; import org.dspace.content.RelationshipType;
import org.dspace.content.Relationship_; import org.dspace.content.Relationship_;
import org.dspace.content.dao.RelationshipDAO; import org.dspace.content.dao.RelationshipDAO;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.AbstractHibernateDAO;
import org.dspace.core.Context; import org.dspace.core.Context;
@@ -25,6 +28,14 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
@Override @Override
public List<Relationship> findByItem(Context context, Item item) throws SQLException { public List<Relationship> findByItem(Context context, Item item) throws SQLException {
return findByItem(context, item, -1, -1);
}
@Override
public List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset)
throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class); Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
@@ -32,7 +43,21 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
criteriaQuery criteriaQuery
.where(criteriaBuilder.or(criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item), .where(criteriaBuilder.or(criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item),
criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item))); criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item)));
return list(context, criteriaQuery, false, Relationship.class, -1, -1); return list(context, criteriaQuery, false, Relationship.class, limit, offset);
}
@Override
public int countByItem(Context context, Item item)
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.or(criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item),
criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item)));
return count(context, criteriaQuery, criteriaBuilder, relationshipRoot);
} }
@Override @Override
@@ -70,14 +95,140 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
@Override @Override
public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType) public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType)
throws SQLException { throws SQLException {
return findByRelationshipType(context, relationshipType, -1, -1);
}
@Override
public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType,
Integer limit, Integer offset) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class); Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.select(relationshipRoot); criteriaQuery.select(relationshipRoot);
criteriaQuery criteriaQuery
.where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType), relationshipType)); .where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType), relationshipType));
return list(context, criteriaQuery, true, Relationship.class, -1, -1); return list(context, criteriaQuery, true, Relationship.class, limit, offset);
} }
@Override
public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType, Integer limit,
Integer offset)
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), criteriaBuilder.or
(criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item),
criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item)));
return list(context, criteriaQuery, true, Relationship.class, limit, offset);
}
@Override
public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType, boolean isLeft,
Integer limit, Integer offset)
throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.select(relationshipRoot);
if (isLeft) {
criteriaQuery
.where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType),
relationshipType),
criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item));
} else {
criteriaQuery
.where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType),
relationshipType),
criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item));
}
return list(context, criteriaQuery, true, Relationship.class, limit, offset);
}
@Override
public List<Relationship> findByTypeName(Context context, String typeName)
throws SQLException {
return this.findByTypeName(context, typeName, -1, -1);
}
@Override
public List<Relationship> findByTypeName(Context context, String typeName, Integer limit, Integer offset)
throws SQLException {
RelationshipTypeService relationshipTypeService = ContentServiceFactory.getInstance()
.getRelationshipTypeService();
List<RelationshipType> relTypes = relationshipTypeService.findByLeftwardOrRightwardTypeName(context, typeName);
List<Integer> ids = new ArrayList<>();
for ( RelationshipType relationshipType : relTypes) {
ids.add(relationshipType.getID());
}
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.where(relationshipRoot.get(Relationship_.relationshipType).in(ids));
return list(context, criteriaQuery, true, Relationship.class, limit, offset);
}
@Override
public int countByRelationshipType(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 count(context, criteriaQuery, criteriaBuilder, relationshipRoot);
}
@Override
public int countRows(Context context) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.select(relationshipRoot);
return count(context, criteriaQuery, criteriaBuilder, relationshipRoot);
}
@Override
public int countByItemAndRelationshipType(Context context, Item item, 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), criteriaBuilder.or
(criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item),
criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item)));
return count(context, criteriaQuery, criteriaBuilder, relationshipRoot);
}
@Override
public int countByTypeName(Context context, String typeName)
throws SQLException {
RelationshipTypeService relationshipTypeService = ContentServiceFactory.getInstance()
.getRelationshipTypeService();
List<RelationshipType> relTypes = relationshipTypeService.findByLeftwardOrRightwardTypeName(context, typeName);
List<Integer> ids = new ArrayList<>();
for ( RelationshipType relationshipType : relTypes) {
ids.add(relationshipType.getID());
}
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.where(relationshipRoot.get(Relationship_.relationshipType).in(ids));
return count(context, criteriaQuery, criteriaBuilder, relationshipRoot);
}
} }

View File

@@ -23,39 +23,55 @@ import org.dspace.core.Context;
public class RelationshipTypeDAOImpl extends AbstractHibernateDAO<RelationshipType> implements RelationshipTypeDAO { public class RelationshipTypeDAOImpl extends AbstractHibernateDAO<RelationshipType> implements RelationshipTypeDAO {
@Override @Override
public RelationshipType findByTypesAndLabels(Context context, EntityType leftType, EntityType rightType, public RelationshipType findbyTypesAndTypeName(Context context, EntityType leftType, EntityType rightType,
String leftLabel, String rightLabel) String leftwardType, String rightwardType)
throws SQLException { throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class);
Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class); Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class);
criteriaQuery.select(relationshipTypeRoot); criteriaQuery.select(relationshipTypeRoot);
criteriaQuery.where( criteriaQuery.where(
criteriaBuilder.and(criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftType), leftType), criteriaBuilder.and(
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightType), rightType), criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftType), leftType),
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftLabel), leftLabel), criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightType), rightType),
criteriaBuilder criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftwardType), leftwardType),
.equal(relationshipTypeRoot.get(RelationshipType_.rightLabel), rightLabel))); criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightwardType), rightwardType)));
return uniqueResult(context, criteriaQuery, false, RelationshipType.class, -1, -1); return uniqueResult(context, criteriaQuery, false, RelationshipType.class, -1, -1);
} }
@Override @Override
public List<RelationshipType> findByLeftOrRightLabel(Context context, String label) throws SQLException { public List<RelationshipType> findByLeftwardOrRightwardTypeName(Context context, String type) throws SQLException {
return findByLeftwardOrRightwardTypeName(context, type, -1, -1);
}
@Override
public List<RelationshipType> findByLeftwardOrRightwardTypeName(Context context, String type, Integer limit,
Integer offset)
throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class);
Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class); Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class);
criteriaQuery.select(relationshipTypeRoot); criteriaQuery.select(relationshipTypeRoot);
criteriaQuery.where( criteriaQuery.where(
criteriaBuilder.or( criteriaBuilder.or(
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftLabel), label), criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftwardType), type),
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightLabel), label) criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightwardType), type)
) )
); );
return list(context, criteriaQuery, true, RelationshipType.class, -1, -1); return list(context, criteriaQuery, true, RelationshipType.class, limit, offset);
} }
@Override @Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException { public List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException {
return findByEntityType(context, entityType, -1, -1);
}
@Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType,
Integer limit, Integer offset) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class);
Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class); Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class);
@@ -67,7 +83,32 @@ public class RelationshipTypeDAOImpl extends AbstractHibernateDAO<RelationshipTy
.equal(relationshipTypeRoot.get(RelationshipType_.rightType), entityType) .equal(relationshipTypeRoot.get(RelationshipType_.rightType), entityType)
) )
); );
return list(context, criteriaQuery, false, RelationshipType.class, -1, -1); return list(context, criteriaQuery, false, RelationshipType.class, limit, offset);
} }
@Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType, Boolean isLeft)
throws SQLException {
return findByEntityType(context, entityType, isLeft, -1, -1);
}
@Override
public List<RelationshipType> findByEntityType(Context context, EntityType entityType, Boolean isLeft,
Integer limit, Integer offset) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class);
Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class);
criteriaQuery.select(relationshipTypeRoot);
if (isLeft) {
criteriaQuery.where(
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftType), entityType)
);
} else {
criteriaQuery.where(
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightType), entityType)
);
}
return list(context, criteriaQuery, false, RelationshipType.class, limit, offset);
}
} }

View File

@@ -12,6 +12,7 @@ import java.util.List;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.InProgressSubmission; import org.dspace.content.InProgressSubmission;
import org.dspace.content.RelationshipMetadataService;
import org.dspace.content.WorkspaceItem; import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.BitstreamFormatService; import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService; import org.dspace.content.service.BitstreamService;
@@ -112,6 +113,8 @@ public abstract class ContentServiceFactory {
*/ */
public abstract EntityService getEntityService(); public abstract EntityService getEntityService();
public abstract RelationshipMetadataService getRelationshipMetadataService();
public InProgressSubmissionService getInProgressSubmissionService(InProgressSubmission inProgressSubmission) { public InProgressSubmissionService getInProgressSubmissionService(InProgressSubmission inProgressSubmission) {
if (inProgressSubmission instanceof WorkspaceItem) { if (inProgressSubmission instanceof WorkspaceItem) {
return getWorkspaceItemService(); return getWorkspaceItemService();

View File

@@ -10,6 +10,7 @@ package org.dspace.content.factory;
import java.util.List; import java.util.List;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.RelationshipMetadataService;
import org.dspace.content.service.BitstreamFormatService; import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService; import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BundleService; import org.dspace.content.service.BundleService;
@@ -78,6 +79,8 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory {
@Autowired(required = true) @Autowired(required = true)
private RelationshipTypeService relationshipTypeService; private RelationshipTypeService relationshipTypeService;
@Autowired(required = true) @Autowired(required = true)
private RelationshipMetadataService relationshipMetadataService;
@Autowired(required = true)
private EntityTypeService entityTypeService; private EntityTypeService entityTypeService;
@Autowired(required = true) @Autowired(required = true)
private EntityService entityService; private EntityService entityService;
@@ -182,4 +185,8 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory {
return entityService; return entityService;
} }
@Override
public RelationshipMetadataService getRelationshipMetadataService() {
return relationshipMetadataService;
}
} }

View File

@@ -36,6 +36,19 @@ public interface EntityService {
*/ */
Entity findByItemId(Context context, UUID itemId) throws SQLException; Entity findByItemId(Context context, UUID itemId) throws SQLException;
/**
* This will construct an Entity object that will be returned with the Item that matches the ItemID that was
* passed along
* as well as a list of relationships for that Item.
* @param context The relevant DSpace context
* @param itemId The ItemID for the Item that is to be used in the Entity object
* @param limit paging limit
* @param offset paging offset
* @return The constructed Entity object with the Item and the list of relationships
* @throws SQLException If something goes wrong
*/
Entity findByItemId(Context context, UUID itemId, Integer limit, Integer offset) throws SQLException;
/** /**
* Returns the EntityType for the Item that is attached to the Entity that is passed along to this method. * Returns the EntityType for the Item that is attached to the Entity that is passed along to this method.
* The EntityType String logic is in the Metadata for that Item and will be searched on in the EntityTypeService * The EntityType String logic is in the Metadata for that Item and will be searched on in the EntityTypeService
@@ -69,12 +82,26 @@ public interface EntityService {
* Retrieves the list of relationships for which their relationshiptype has a left or right label that is * Retrieves the list of relationships for which their relationshiptype has a left or right label that is
* equal to the passed along label String * equal to the passed along label String
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param label The label that needs to be in the relationshiptype of the relationship * @param typeName The label that needs to be in the relationshiptype of the relationship
* @return The list of relationships that have a relationshiptype with a left or right label * @return The list of relationships that have a relationshiptype with a left or right label
* that is equal to the label param * that is equal to the label param
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
List<Relationship> getRelationsByLabel(Context context, String label) throws SQLException; List<Relationship> getRelationsByTypeName(Context context, String typeName) throws SQLException;
/**
* Retrieves the list of relationships for which their relationshiptype has a left or right label that is
* equal to the passed along label String
* @param context The relevant DSpace context
* @param typeName The label that needs to be in the relationshiptype of the relationship
* @param limit paging limit
* @param offset paging offset
* @return The list of relationships that have a relationshiptype with a left or right label
* that is equal to the label param
* @throws SQLException If something goes wrong
*/
List<Relationship> getRelationsByTypeName(Context context, String typeName, Integer limit, Integer offset)
throws SQLException;
/** /**
* Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given * Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given
@@ -89,6 +116,22 @@ public interface EntityService {
*/ */
List<RelationshipType> getAllRelationshipTypes(Context context, Entity entity) throws SQLException; List<RelationshipType> getAllRelationshipTypes(Context context, Entity entity) throws SQLException;
/**
* Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given
* Entity
* in either the leftEntityType or the rightEntityType variables
* @param context The relevant DSpace context
* @param entity The Entity for which the EntityType should be checked for relationships
* @param limit paging limit
* @param offset paging offset
* @return The list of relationships that each contain a relationshiptype in which there is a right or left
* entity type that
* is equal to the entity type for the given entity
* @throws SQLException If something goes wrong
*/
List<RelationshipType> getAllRelationshipTypes(Context context, Entity entity, Integer limit, Integer offset)
throws SQLException;
/** /**
* Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given * Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given
* Entity * Entity
@@ -101,6 +144,23 @@ public interface EntityService {
*/ */
List<RelationshipType> getLeftRelationshipTypes(Context context, Entity entity) throws SQLException; List<RelationshipType> getLeftRelationshipTypes(Context context, Entity entity) throws SQLException;
/**
* Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given
* Entity
* in the leftEntityType
* @param context The relevant DSpace context
* @param entity The Entity for which the EntityType should be checked for relationships
* @param isLeft Boolean value used to filter by left_type or right_type. If true left_type results only
* else right_type results.
* @param limit paging limit
* @param offset paging offset
* @return The list of relationships that each contain a relationshiptype in which there is a left entity type that
* is equal to the entity type for the given entity
* @throws SQLException If something goes wrong
*/
List<RelationshipType> getLeftRelationshipTypes(Context context, Entity entity, boolean isLeft,
Integer limit, Integer offset) throws SQLException;
/** /**
* Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given * Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given
* Entity * Entity
@@ -113,15 +173,46 @@ public interface EntityService {
*/ */
List<RelationshipType> getRightRelationshipTypes(Context context, Entity entity) throws SQLException; List<RelationshipType> getRightRelationshipTypes(Context context, Entity entity) throws SQLException;
/**
* Retrieves the list of relationships that have a relationshiptype that contains the EntityType for the given
* Entity
* in the rightEntityType
* @param context The relevant DSpace context
* @param entity The Entity for which the EntityType should be checked for relationships
* @param isLeft Boolean value used to filter by left_type or right_type. If true left_type results only
* else right_type results.
* @param limit paging limit
* @param offset paging offset
* @return The list of relationships that each contain a relationshiptype in which there is a right entity type that
* is equal to the entity type for the given entity
* @throws SQLException If something goes wrong
*/
List<RelationshipType> getRightRelationshipTypes(Context context, Entity entity, boolean isLeft,
Integer limit, Integer offset) throws SQLException;
/** /**
* Retrieves a list of RelationshipType objects for which either their left or right label is equal to the * Retrieves a list of RelationshipType objects for which either their left or right label is equal to the
* label parameter that's being passed along * label parameter that's being passed along
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param label The label for which the relationshiptype's labels must be checked * @param typeName The typeName for which the relationshiptype's labels must be checked
* @return The list of relationshiptypes that each contain a left or right label that is equal * @return The list of relationshiptypes that each contain a left or right label that is equal
* to the given label parameter * to the given label parameter
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
List<RelationshipType> getRelationshipTypesByLabel(Context context, String label) throws SQLException; List<RelationshipType> getRelationshipTypesByTypeName(Context context, String typeName) throws SQLException;
/**
* Retrieves a list of RelationshipType objects for which either their left or right label is equal to the
* label parameter that's being passed along
* @param context The relevant DSpace context
* @param type The label for which the relationshiptype's labels must be checked
* @param limit paging limit
* @param offset paging offset
* @return The list of relationshiptypes that each contain a left or right label that is equal
* to the given label parameter
* @throws SQLException If something goes wrong
*/
List<RelationshipType> getRelationshipTypesByTypeName(Context context, String type,
Integer limit, Integer offset) throws SQLException;
} }

View File

@@ -37,6 +37,16 @@ public interface EntityTypeService extends DSpaceCRUDService<EntityType> {
*/ */
public List<EntityType> findAll(Context context) throws SQLException; public List<EntityType> findAll(Context context) throws SQLException;
/**
* Retrieves all the EntityType objects currently in the system
* @param context The relevant DSpace context
* @param limit paging limit
* @param offset paging offset
* @return A list of all EntityType objects
* @throws SQLException If something goes wrong
*/
List<EntityType> findAll(Context context, Integer limit, Integer offset) throws SQLException;
/** /**
* This method creates an EntityType object in the database with the given entityTypeString as it's label * This method creates an EntityType object in the database with the given entityTypeString as it's label
* @param context The relevant DSpace context * @param context The relevant DSpace context

View File

@@ -24,10 +24,8 @@ import org.dspace.content.Community;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.MetadataValue; import org.dspace.content.MetadataValue;
import org.dspace.content.RelationshipMetadataValue;
import org.dspace.content.Thumbnail; import org.dspace.content.Thumbnail;
import org.dspace.content.WorkspaceItem; import org.dspace.content.WorkspaceItem;
import org.dspace.content.virtual.VirtualMetadataPopulator;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group; import org.dspace.eperson.Group;
@@ -40,7 +38,7 @@ import org.dspace.eperson.Group;
* @author kevinvandevelde at atmire.com * @author kevinvandevelde at atmire.com
*/ */
public interface ItemService public interface ItemService
extends DSpaceObjectService<Item>, DSpaceObjectLegacySupportService<Item>, IndexableObjectService<Item, UUID> { extends DSpaceObjectService<Item>, DSpaceObjectLegacySupportService<Item>, IndexableObjectService<Item, UUID> {
public Thumbnail getThumbnail(Context context, Item item, boolean requireOriginal) throws SQLException; public Thumbnail getThumbnail(Context context, Item item, boolean requireOriginal) throws SQLException;
@@ -205,7 +203,7 @@ public interface ItemService
* @throws SQLException if database error * @throws SQLException if database error
*/ */
public Iterator<Item> findInArchiveOrWithdrawnNonDiscoverableModifiedSince(Context context, Date since) public Iterator<Item> findInArchiveOrWithdrawnNonDiscoverableModifiedSince(Context context, Date since)
throws SQLException; throws SQLException;
/** /**
* Get all the items (including private and withdrawn) in this collection. The order is indeterminate. * Get all the items (including private and withdrawn) in this collection. The order is indeterminate.
@@ -677,19 +675,6 @@ public interface ItemService
*/ */
boolean isInProgressSubmission(Context context, Item item) throws SQLException; boolean isInProgressSubmission(Context context, Item item) throws SQLException;
/**
* This method retrieves a list of MetadataValue objects that get constructed from processing
* the given Item's Relationships through the config given to the {@link VirtualMetadataPopulator}
* @param item The Item that will be processed through it's Relationships
* @param enableVirtualMetadata This parameter will determine whether the list of Relationship metadata
* should be populated with metadata that is being generated through the
* VirtualMetadataPopulator functionality or not
* @return The list of MetadataValue objects constructed through the Relationships
*/
public List<RelationshipMetadataValue> getRelationshipMetadata(Item item, boolean enableVirtualMetadata);
/** /**
* Get metadata for the DSpace Object in a chosen schema. * Get metadata for the DSpace Object in a chosen schema.
* See <code>MetadataSchema</code> for more information about schemas. * See <code>MetadataSchema</code> for more information about schemas.

View File

@@ -30,7 +30,19 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
* @return The list of relationships for which each relationship adheres to the above listed constraint * @return The list of relationships for which each relationship adheres to the above listed constraint
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
public List<Relationship> findByItem(Context context,Item item) throws SQLException; public List<Relationship> findByItem(Context context, Item item) throws SQLException;
/**
* Retrieves the list of Relationships currently in the system for which the given Item is either
* a leftItem or a rightItem object
* @param context The relevant DSpace context
* @param item The Item that has to be the left or right item for the relationship to be included in the list
* @param limit paging limit
* @param offset paging offset
* @return The list of relationships for which each relationship adheres to the above listed constraint
* @throws SQLException If something goes wrong
*/
List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset) throws SQLException;
/** /**
* Retrieves the full list of relationships currently in the system * Retrieves the full list of relationships currently in the system
@@ -40,6 +52,16 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
*/ */
public List<Relationship> findAll(Context context) throws SQLException; public List<Relationship> findAll(Context context) throws SQLException;
/**
* Retrieves the full list of relationships currently in the system
* @param context The relevant DSpace context
* @param limit paging limit
* @param offset paging offset
* @return The list of all relationships currently in the system
* @throws SQLException If something goes wrong
*/
List<Relationship> findAll(Context context, Integer limit, Integer offset) throws SQLException;
/** /**
* This method creates a relationship object in the database equal to the given relationship param * This method creates a relationship object in the database equal to the given relationship param
* if this is a valid relationship * if this is a valid relationship
@@ -87,9 +109,39 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
RelationshipType relationshipType) RelationshipType relationshipType)
throws SQLException; throws SQLException;
/**
* 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 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, int limit, int offset)
throws SQLException;
/**
* 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 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
* @param isLeft Is the item left or right
* @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, boolean isLeft,
int limit, int offset)
throws SQLException;
/** /**
* This method will update the place for the Relationship and all other relationships found by the items and * This method will update the place for the Relationship and all other relationships found by the items and
* relationship type of the given Relatonship. It will give this Relationship the last place in both the * relationship type of the given Relationship. It will give this Relationship the last place in both the
* left and right place determined by querying for the list of leftRelationships and rightRelationships * left and right place determined by querying for the list of leftRelationships and rightRelationships
* by the leftItem, rightItem and relationshipType of the given Relationship. * by the leftItem, rightItem and relationshipType of the given Relationship.
* @param context The relevant DSpace context * @param context The relevant DSpace context
@@ -116,7 +168,7 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
/** /**
* This method returns a list of Relationship objets for which the relationshipType property is equal to the given * This method returns a list of Relationship objects for which the relationshipType property is equal to the given
* RelationshipType object * RelationshipType object
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param relationshipType The RelationshipType object that will be used to check the Relationship on * @param relationshipType The RelationshipType object that will be used to check the Relationship on
@@ -126,6 +178,20 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
*/ */
List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType) throws SQLException; List<Relationship> findByRelationshipType(Context context, 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
* @param limit paging limit
* @param offset paging offset
* @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, Integer limit,
Integer offset) throws SQLException;
/** /**
* This method is used to construct a Relationship object with all it's variables * This method is used to construct a Relationship object with all it's variables
* @param c The relevant DSpace context * @param c The relevant DSpace context
@@ -134,6 +200,26 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
* @param relationshipType The RelationshipType object for the relationship * @param relationshipType The RelationshipType object for the relationship
* @param leftPlace The leftPlace integer for the relationship * @param leftPlace The leftPlace integer for the relationship
* @param rightPlace The rightPlace integer for the relationship * @param rightPlace The rightPlace integer for the relationship
* @param leftwardValue The leftwardValue string for the relationship
* @param rightwardValue The rightwardValue string for the relationship
* @return The created Relationship object with the given properties
* @throws AuthorizeException If something goes wrong
* @throws SQLException If something goes wrong
*/
Relationship create(Context c, Item leftItem, Item rightItem, RelationshipType relationshipType,
int leftPlace, int rightPlace, String leftwardValue, String rightwardValue)
throws AuthorizeException, SQLException;
/**
* This method is used to construct a Relationship object with all it's variables,
* except the leftward and rightward labels
* @param c The relevant DSpace context
* @param leftItem The leftItem Item object for the relationship
* @param rightItem The rightItem Item object for the relationship
* @param relationshipType The RelationshipType object for the relationship
* @param leftPlace The leftPlace integer for the relationship
* @param rightPlace The rightPlace integer for the relationship
* @return The created Relationship object with the given properties * @return The created Relationship object with the given properties
* @throws AuthorizeException If something goes wrong * @throws AuthorizeException If something goes wrong
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
@@ -141,4 +227,82 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
Relationship create(Context c, Item leftItem, Item rightItem, RelationshipType relationshipType, Relationship create(Context c, Item leftItem, Item rightItem, RelationshipType relationshipType,
int leftPlace, int rightPlace) int leftPlace, int rightPlace)
throws AuthorizeException, SQLException; throws AuthorizeException, SQLException;
/**
* This method returns a list of Relationship objects for the given typeName
* @param context The relevant DSpace context
* @param typeName The leftward or rightward typeName of the relationship type
* @return A list of Relationship objects that have the given RelationshipType object as the
* relationshipType property
* @throws SQLException If something goes wrong
*/
List<Relationship> findByTypeName(Context context, String typeName) throws SQLException;
/**
* This method returns a list of Relationship objects for the given typeName
* @param context The relevant DSpace context
* @param typeName The leftward or rightward typeName of the relationship type
* @param limit paging limit
* @param offset paging offset
* @return A list of Relationship objects that have the given RelationshipType object as the
* relationshipType property
* @throws SQLException If something goes wrong
*/
List<Relationship> findByTypeName(Context context, String typeName, Integer limit, Integer offset)
throws SQLException;
/**
* counts all relationships
*
* @param context DSpace context object
* @return total relationships
* @throws SQLException if database error
*/
int countTotal(Context context) throws SQLException;
/**
* Count total number of relationships (rows in relationship table) by a relationship type
*
* @param context context
* @param relationshipType relationship type to filter by
* @return total count
* @throws SQLException if database error
*/
int countByRelationshipType(Context context, RelationshipType relationshipType) throws SQLException;
/**
* This method returns a count of Relationship objects that have the given Item object
* as a leftItem or a rightItem
* @param context The relevant DSpace context
* @param item The item that should be either a leftItem or a rightItem of all
* the Relationship objects in the returned list
* @return The list of Relationship objects that contain either a left or a
* right item that is equal to the given item
* @throws SQLException If something goes wrong
*/
int countByItem(Context context, Item item) throws SQLException;
/**
* Count total number of relationships (rows in relationship table) by a relationship type
*
* @param context context
* @param relationshipType relationship type to filter by
* @return total count
* @throws SQLException if database error
*/
int countByItemAndRelationshipType(Context context, Item item, RelationshipType relationshipType)
throws SQLException;
/**
* Count total number of relationships (rows in relationship table)
* by a relationship leftward or rightward typeName
*
* @param context context
* @param typeName typeName of relationship
* @return total count
* @throws SQLException if database error
*/
int countByTypeName(Context context, String typeName)
throws SQLException;
} }

View File

@@ -29,20 +29,20 @@ public interface RelationshipTypeService extends DSpaceCRUDService<RelationshipT
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong with authorizations * @throws AuthorizeException If something goes wrong with authorizations
*/ */
RelationshipType create(Context context,RelationshipType relationshipType) throws SQLException, AuthorizeException; RelationshipType create(Context context, RelationshipType relationshipType) throws SQLException, AuthorizeException;
/** /**
* Retrieves a RelationshipType for which the given parameters all match the one in the returned RelationshipType * Retrieves a RelationshipType for which the given parameters all match the one in the returned RelationshipType
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param leftType The rightType EntityType that needs to match for the returned RelationshipType * @param leftType The rightType EntityType that needs to match for the returned RelationshipType
* @param rightType The rightType EntityType that needs to match for the returned RelationshipType * @param rightType The rightType EntityType that needs to match for the returned RelationshipType
* @param leftLabel The leftLabel String that needs to match for the returned RelationshipType * @param leftwardType The leftwardType String that needs to match for the returned RelationshipType
* @param rightLabel The rightLabel String that needs to match for the returned RelationshipType * @param rightwardType The rightwardType String that needs to match for the returned RelationshipType
* @return * @return
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
RelationshipType findbyTypesAndLabels(Context context,EntityType leftType,EntityType rightType, RelationshipType findbyTypesAndTypeName(Context context, EntityType leftType, EntityType rightType,
String leftLabel,String rightLabel) String leftwardType, String rightwardType)
throws SQLException; throws SQLException;
/** /**
@@ -54,15 +54,40 @@ public interface RelationshipTypeService extends DSpaceCRUDService<RelationshipT
List<RelationshipType> findAll(Context context) throws SQLException; List<RelationshipType> findAll(Context context) throws SQLException;
/** /**
* Retrieves all RelationshipType objects that have a left or right label that is * Retrieves all RelationshipType objects currently in the system
* @param context The relevant DSpace context
* @param limit paging limit
* @param offset paging offset
* @return The list of all RelationshipType objects currently in the system
* @throws SQLException If something goes wrong
*/
List<RelationshipType> findAll(Context context, Integer limit, Integer offset) throws SQLException;
/**
* Retrieves all RelationshipType objects that have a left or right type that is
* equal to the given String * equal to the given String
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param label The label that has to match * @param typeName The label that has to match
* @return The list of all RelationshipType objects that have a left or right label * @return The list of all RelationshipType objects that have a left or right label
* that is equal to the given label param * that is equal to the given label param
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
List<RelationshipType> findByLeftOrRightLabel(Context context, String label) throws SQLException; List<RelationshipType> findByLeftwardOrRightwardTypeName(Context context, String typeName) throws SQLException;
/**
* Retrieves all RelationshipType objects that have a left or right label that is
* equal to the given String
* @param context The relevant DSpace context
* @param typeName The typeName that has to match
* @param limit paging limit
* @param offset paging offset
* @return The list of all RelationshipType objects that have a left or right label
* that is equal to the given label param
* @throws SQLException If something goes wrong
*/
List<RelationshipType> findByLeftwardOrRightwardTypeName(Context context, String typeName, Integer limit,
Integer offset)
throws SQLException;
/** /**
* Returns a list of RelationshipType objects for which the given EntityType is equal to either the leftType * Returns a list of RelationshipType objects for which the given EntityType is equal to either the leftType
@@ -75,13 +100,48 @@ public interface RelationshipTypeService extends DSpaceCRUDService<RelationshipT
*/ */
List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException; List<RelationshipType> findByEntityType(Context context, EntityType entityType) throws SQLException;
List<RelationshipType> findByEntityType(Context context, EntityType entityType, Integer limit, Integer offset)
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
* @param isLeft Boolean value used to filter by left_type or right_type. If true left_type results only
* else right_type results.
* @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, boolean isLeft)
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
* @param isLeft Boolean value used to filter by left_type or right_type. If true left_type results only
* else right_type results.
* @param limit paging limit
* @param offset paging offset
* @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, boolean isLeft,
Integer limit, Integer offset)
throws SQLException;
/** /**
* This method will support the creation of a RelationshipType object with the given parameters * This method will support the creation of a RelationshipType object with the given parameters
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param leftEntityType The leftEntityType EntityType object for this relationshipType * @param leftEntityType The leftEntityType EntityType object for this relationshipType
* @param rightEntityType The rightEntityType EntityType object for this relationshipType * @param rightEntityType The rightEntityType EntityType object for this relationshipType
* @param leftLabel The leftLabel String object for this relationshipType * @param leftwardType The leftwardType String object for this relationshipType
* @param rightLabel The rightLabel String object for this relationshipType * @param rightwardType The rightwardType String object for this relationshipType
* @param leftCardinalityMinInteger The leftCardinalityMinInteger Integer object for this relationshipType * @param leftCardinalityMinInteger The leftCardinalityMinInteger Integer object for this relationshipType
* @param leftCardinalityMaxInteger The leftCardinalityMaxInteger Integer object for this relationshipType * @param leftCardinalityMaxInteger The leftCardinalityMaxInteger Integer object for this relationshipType
* @param rightCardinalityMinInteger The rightCardinalityMinInteger Integer object for this relationshipType * @param rightCardinalityMinInteger The rightCardinalityMinInteger Integer object for this relationshipType
@@ -90,8 +150,9 @@ public interface RelationshipTypeService extends DSpaceCRUDService<RelationshipT
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong * @throws AuthorizeException If something goes wrong
*/ */
RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType, String leftLabel, RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType,
String rightLabel, Integer leftCardinalityMinInteger, Integer leftCardinalityMaxInteger, String leftwardType, String rightwardType, Integer leftCardinalityMinInteger,
Integer rightCardinalityMinInteger, Integer rightCardinalityMaxInteger) Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger,
Integer rightCardinalityMaxInteger)
throws SQLException, AuthorizeException; throws SQLException, AuthorizeException;
} }

View File

@@ -65,6 +65,7 @@ public class Collected implements VirtualMetadataConfiguration {
* Generic setter for the useForPlace property * Generic setter for the useForPlace property
* @param useForPlace The boolean value that the useForPlace property will be set to * @param useForPlace The boolean value that the useForPlace property will be set to
*/ */
@Override
public void setUseForPlace(boolean useForPlace) { public void setUseForPlace(boolean useForPlace) {
this.useForPlace = useForPlace; this.useForPlace = useForPlace;
} }
@@ -73,10 +74,19 @@ public class Collected implements VirtualMetadataConfiguration {
* Generic getter for the useForPlace property * Generic getter for the useForPlace property
* @return The useForPlace to be used by this bean * @return The useForPlace to be used by this bean
*/ */
@Override
public boolean getUseForPlace() { public boolean getUseForPlace() {
return useForPlace; return useForPlace;
} }
@Override
public void setPopulateWithNameVariant(boolean populateWithNameVariant) { }
@Override
public boolean getPopulateWithNameVariant() {
return false;
}
/** /**
* this method will retrieve the metadata values from the given item for all the metadata fields listed * this method will retrieve the metadata values from the given item for all the metadata fields listed
* in the fields property and it'll return all those values as a list * in the fields property and it'll return all those values as a list

View File

@@ -44,6 +44,7 @@ public class Concatenate implements VirtualMetadataConfiguration {
*/ */
private boolean useForPlace = false; private boolean useForPlace = false;
private boolean populateWithNameVariant = false;
/** /**
* Generic getter for the fields property * Generic getter for the fields property
* @return The list of fields to be used in this bean * @return The list of fields to be used in this bean
@@ -80,6 +81,7 @@ public class Concatenate implements VirtualMetadataConfiguration {
* Generic setter for the useForPlace property * Generic setter for the useForPlace property
* @param useForPlace The boolean value that the useForPlace property will be set to * @param useForPlace The boolean value that the useForPlace property will be set to
*/ */
@Override
public void setUseForPlace(boolean useForPlace) { public void setUseForPlace(boolean useForPlace) {
this.useForPlace = useForPlace; this.useForPlace = useForPlace;
} }
@@ -88,10 +90,21 @@ public class Concatenate implements VirtualMetadataConfiguration {
* Generic getter for the useForPlace property * Generic getter for the useForPlace property
* @return The useForPlace to be used by this bean * @return The useForPlace to be used by this bean
*/ */
@Override
public boolean getUseForPlace() { public boolean getUseForPlace() {
return useForPlace; return useForPlace;
} }
@Override
public void setPopulateWithNameVariant(boolean populateWithNameVariant) {
this.populateWithNameVariant = populateWithNameVariant;
}
@Override
public boolean getPopulateWithNameVariant() {
return populateWithNameVariant;
}
/** /**
* this method will retrieve the metadata values from the given item for all the metadata fields listed * this method will retrieve the metadata values from the given item for all the metadata fields listed
* in the fields property and it'll concatenate all those values together with the separator specified * in the fields property and it'll concatenate all those values together with the separator specified
@@ -100,6 +113,7 @@ public class Concatenate implements VirtualMetadataConfiguration {
* @param item The item that will be used to either retrieve metadata values from * @param item The item that will be used to either retrieve metadata values from
* @return The String value for all of the retrieved metadatavalues combined with the separator * @return The String value for all of the retrieved metadatavalues combined with the separator
*/ */
@Override
public List<String> getValues(Context context, Item item) { public List<String> getValues(Context context, Item item) {
List<String> resultValues = new LinkedList<>(); List<String> resultValues = new LinkedList<>();

View File

@@ -120,6 +120,7 @@ public class Related implements VirtualMetadataConfiguration {
* Generic setter for the useForPlace property * Generic setter for the useForPlace property
* @param useForPlace The boolean value that the useForPlace property will be set to * @param useForPlace The boolean value that the useForPlace property will be set to
*/ */
@Override
public void setUseForPlace(boolean useForPlace) { public void setUseForPlace(boolean useForPlace) {
this.useForPlace = useForPlace; this.useForPlace = useForPlace;
} }
@@ -128,10 +129,19 @@ public class Related implements VirtualMetadataConfiguration {
* Generic getter for the useForPlace property * Generic getter for the useForPlace property
* @return The useForPlace to be used by this bean * @return The useForPlace to be used by this bean
*/ */
@Override
public boolean getUseForPlace() { public boolean getUseForPlace() {
return useForPlace; return useForPlace;
} }
@Override
public void setPopulateWithNameVariant(boolean populateWithNameVariant) { }
@Override
public boolean getPopulateWithNameVariant() {
return false;
}
/** /**
* This method will find the correct Relationship from the given item to retrieve the other item from it * This method will find the correct Relationship from the given item to retrieve the other item from it
* and pass this along to the next VirtualBean that's stored in this class. * and pass this along to the next VirtualBean that's stored in this class.
@@ -142,6 +152,7 @@ public class Related implements VirtualMetadataConfiguration {
* Will return an empty list if no relationships are found * Will return an empty list if no relationships are found
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
@Override
public List<String> getValues(Context context, Item item) throws SQLException { public List<String> getValues(Context context, Item item) throws SQLException {
Entity entity = entityService.findByItemId(context, item.getID()); Entity entity = entityService.findByItemId(context, item.getID());
EntityType entityType = entityService.getType(context, entity); EntityType entityType = entityService.getType(context, entity);
@@ -149,8 +160,8 @@ public class Related implements VirtualMetadataConfiguration {
List<RelationshipType> relationshipTypes = entityService.getAllRelationshipTypes(context, entity); List<RelationshipType> relationshipTypes = entityService.getAllRelationshipTypes(context, entity);
List<RelationshipType> possibleRelationshipTypes = new LinkedList<>(); List<RelationshipType> possibleRelationshipTypes = new LinkedList<>();
for (RelationshipType relationshipType : relationshipTypes) { for (RelationshipType relationshipType : relationshipTypes) {
if (StringUtils.equals(relationshipType.getLeftLabel(), relationshipTypeString) || StringUtils if (StringUtils.equals(relationshipType.getLeftwardType(), relationshipTypeString) || StringUtils
.equals(relationshipType.getRightLabel(), relationshipTypeString)) { .equals(relationshipType.getRightwardType(), relationshipTypeString)) {
possibleRelationshipTypes.add(relationshipType); possibleRelationshipTypes.add(relationshipType);
} }
} }

View File

@@ -38,4 +38,12 @@ public class UUIDValue implements VirtualMetadataConfiguration {
public boolean getUseForPlace() { public boolean getUseForPlace() {
return useForPlace; return useForPlace;
} }
@Override
public void setPopulateWithNameVariant(boolean populateWithNameVariant) { }
@Override
public boolean getPopulateWithNameVariant() {
return false;
}
} }

View File

@@ -42,4 +42,18 @@ public interface VirtualMetadataConfiguration {
* @return The useForPlace to be used by this bean * @return The useForPlace to be used by this bean
*/ */
boolean getUseForPlace(); boolean getUseForPlace();
/**
* Generic setter for the populateWithNameVariant
* This property defines whether the value should be retrieved from the left/rightward on the Relationship (true)
* or through the configuration and usual way (false)
* @param populateWithNameVariant The boolean value that the populateWithNameVariant property will be set to
*/
void setPopulateWithNameVariant(boolean populateWithNameVariant);
/**
* Generic getter for the populateWithNameVariant property
* @return The populatewithNameVariant to be used by this bean
*/
boolean getPopulateWithNameVariant();
} }

View File

@@ -42,17 +42,17 @@ public class VirtualMetadataPopulator {
/** /**
* This method will return a boolean indicating whether the useForPlace is true or false for the given * This method will return a boolean indicating whether the useForPlace is true or false for the given
* RelationshipType for the left or right label as indicated by the second parameter. * RelationshipType for the left or right type as indicated by the second parameter.
* @param relationshipType The relationshipType for which this should be checked * @param relationshipType The relationshipType for which this should be checked
* @param isLeft The boolean indicating whether to check the left or the right label * @param isLeft The boolean indicating whether to check the left or the right type
* @return A boolean indicating whether the useForPlace is true or not for the given parameters * @return A boolean indicating whether the useForPlace is true or not for the given parameters
*/ */
public boolean isUseForPlaceTrueForRelationshipType(RelationshipType relationshipType, boolean isLeft) { public boolean isUseForPlaceTrueForRelationshipType(RelationshipType relationshipType, boolean isLeft) {
HashMap<String, VirtualMetadataConfiguration> hashMaps; HashMap<String, VirtualMetadataConfiguration> hashMaps;
if (isLeft) { if (isLeft) {
hashMaps = this.getMap().get(relationshipType.getLeftLabel()); hashMaps = this.getMap().get(relationshipType.getLeftwardType());
} else { } else {
hashMaps = this.getMap().get(relationshipType.getRightLabel()); hashMaps = this.getMap().get(relationshipType.getRightwardType());
} }
if (hashMaps != null) { if (hashMaps != null) {
for (Map.Entry<String, VirtualMetadataConfiguration> entry : hashMaps.entrySet()) { for (Map.Entry<String, VirtualMetadataConfiguration> entry : hashMaps.entrySet()) {

View File

@@ -66,10 +66,16 @@ public abstract class AbstractHibernateDAO<T> implements GenericDAO<T> {
@Override @Override
public List<T> findAll(Context context, Class<T> clazz) throws SQLException { public List<T> findAll(Context context, Class<T> clazz) throws SQLException {
return findAll(context, clazz, -1, -1);
}
@Override
public List<T> findAll(Context context, Class<T> clazz, Integer limit, Integer offset) throws SQLException {
CriteriaQuery criteriaQuery = getCriteriaQuery(getCriteriaBuilder(context), clazz); CriteriaQuery criteriaQuery = getCriteriaQuery(getCriteriaBuilder(context), clazz);
Root<T> root = criteriaQuery.from(clazz); Root<T> root = criteriaQuery.from(clazz);
criteriaQuery.select(root); criteriaQuery.select(root);
return executeCriteriaQuery(context, criteriaQuery, false, -1, -1); return executeCriteriaQuery(context, criteriaQuery, false, limit, offset);
} }
@Override @Override

View File

@@ -58,6 +58,18 @@ public interface GenericDAO<T> {
*/ */
public List<T> findAll(Context context, Class<T> clazz) throws SQLException; public List<T> findAll(Context context, Class<T> clazz) throws SQLException;
/**
* Fetch all persisted instances of a given object type.
*
* @param context The relevant DSpace Context.
* @param clazz the desired type.
* @param limit paging limit
* @param offset paging offset
* @return list of DAOs of the same type as clazz
* @throws SQLException if database error
*/
List<T> findAll(Context context, Class<T> clazz, Integer limit, Integer offset) throws SQLException;
/** /**
* Execute a JPQL query returning a unique result. * Execute a JPQL query returning a unique result.
* *

View File

@@ -360,6 +360,11 @@ public class LegacyPluginServiceImpl implements PluginService {
return null; return null;
} }
@Override
public void clearNamedPluginClasses() {
namedPluginClasses.clear();
}
/** /**
* Returns whether a plugin exists which implements the specified interface * Returns whether a plugin exists which implements the specified interface
* and has a specified name. If a matching plugin is found to be configured, * and has a specified name. If a matching plugin is found to be configured,

View File

@@ -84,4 +84,9 @@ public interface PluginService {
* @return instance of plugin * @return instance of plugin
*/ */
public Object getSinglePlugin(Class interfaceClass); public Object getSinglePlugin(Class interfaceClass);
/**
* This method has been created to have a way of clearing the cache kept in the PluginService
*/
public void clearNamedPluginClasses();
} }

View File

@@ -10,9 +10,9 @@ package org.dspace.discovery;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Set;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
@@ -140,26 +140,26 @@ public class SearchUtils {
private static List<DiscoveryConfiguration> getAllDiscoveryConfigurations(String prefix, private static List<DiscoveryConfiguration> getAllDiscoveryConfigurations(String prefix,
List<Collection> collections, Item item) List<Collection> collections, Item item)
throws SQLException { throws SQLException {
Map<String, DiscoveryConfiguration> result = new HashMap<String, DiscoveryConfiguration>(); Set<DiscoveryConfiguration> result = new HashSet<>();
for (Collection collection : collections) { for (Collection collection : collections) {
DiscoveryConfiguration configuration = getDiscoveryConfiguration(prefix, collection); DiscoveryConfiguration configuration = getDiscoveryConfiguration(prefix, collection);
if (!result.containsKey(configuration.getId())) { result.add(configuration);
result.put(configuration.getId(), configuration);
}
} }
//Add alwaysIndex configurations
DiscoveryConfigurationService configurationService = getConfigurationService();
result.addAll(configurationService.getIndexAlwaysConfigurations());
//Also add one for the default //Also add one for the default
addConfigurationIfExists(result, prefix); addConfigurationIfExists(result, prefix);
return Arrays.asList(result.values().toArray(new DiscoveryConfiguration[result.size()])); return Arrays.asList(result.toArray(new DiscoveryConfiguration[result.size()]));
} }
private static void addConfigurationIfExists(Map<String, DiscoveryConfiguration> result, String confName) { private static void addConfigurationIfExists(Set<DiscoveryConfiguration> result, String confName) {
DiscoveryConfiguration configurationExtra = getDiscoveryConfigurationByName(confName); DiscoveryConfiguration configurationExtra = getDiscoveryConfigurationByName(confName);
if (!result.containsKey(configurationExtra.getId())) { result.add(configurationExtra);
result.put(configurationExtra.getId(), configurationExtra);
}
} }
} }

View File

@@ -51,6 +51,22 @@ public class DiscoveryConfiguration implements InitializingBean {
private DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration; private DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration;
private DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration; private DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration;
private boolean spellCheckEnabled; private boolean spellCheckEnabled;
private boolean indexAlways = false;
/**
* The `indexAlways` property determines whether the configuration should always be included when indexing items.
* The default value is false which implies the configuration is only used when it matches the collection or if
* it's the default configuration
* When set to true, the configuration is also used to index an item without a specific collection mapping
* This can be used for displaying different facets depending on the type of item instead of the collection
*/
public boolean isIndexAlways() {
return indexAlways;
}
public void setIndexAlways(boolean indexAlways) {
this.indexAlways = indexAlways;
}
public String getId() { public String getId() {
return id; return id;

View File

@@ -7,6 +7,7 @@
*/ */
package org.dspace.discovery.configuration; package org.dspace.discovery.configuration;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -75,6 +76,22 @@ public class DiscoveryConfigurationService {
} }
} }
/**
* Retrieves a list of all DiscoveryConfiguration objects where
* {@link org.dspace.discovery.configuration.DiscoveryConfiguration#isIndexAlways()} is true
* These configurations should always be included when indexing
*/
public List<DiscoveryConfiguration> getIndexAlwaysConfigurations() {
List<DiscoveryConfiguration> configs = new ArrayList<>();
for (String key : map.keySet()) {
DiscoveryConfiguration config = map.get(key);
if (config.isIndexAlways()) {
configs.add(config);
}
}
return configs;
}
public static void main(String[] args) { public static void main(String[] args) {
System.out.println(DSpaceServicesFactory.getInstance().getServiceManager().getServicesNames().size()); System.out.println(DSpaceServicesFactory.getInstance().getServiceManager().getServicesNames().size());
DiscoveryConfigurationService mainService = DSpaceServicesFactory.getInstance().getServiceManager() DiscoveryConfigurationService mainService = DSpaceServicesFactory.getInstance().getServiceManager()

View File

@@ -7,16 +7,28 @@
*/ */
package org.dspace.harvest; package org.dspace.harvest;
import static org.dspace.harvest.OAIHarvester.OAI_ADDRESS_ERROR;
import static org.dspace.harvest.OAIHarvester.OAI_DMD_ERROR;
import static org.dspace.harvest.OAIHarvester.OAI_ORE_ERROR;
import static org.dspace.harvest.OAIHarvester.OAI_SET_ERROR;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import ORG.oclc.oai.harvester2.verb.Identify;
import ORG.oclc.oai.harvester2.verb.ListIdentifiers;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.harvest.dao.HarvestedCollectionDAO; import org.dspace.harvest.dao.HarvestedCollectionDAO;
import org.dspace.harvest.service.HarvestedCollectionService; import org.dspace.harvest.service.HarvestedCollectionService;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.DOMBuilder;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
/** /**
@@ -27,6 +39,10 @@ import org.springframework.beans.factory.annotation.Autowired;
* @author kevinvandevelde at atmire.com * @author kevinvandevelde at atmire.com
*/ */
public class HarvestedCollectionServiceImpl implements HarvestedCollectionService { public class HarvestedCollectionServiceImpl implements HarvestedCollectionService {
private static final Namespace ORE_NS = Namespace.getNamespace("http://www.openarchives.org/ore/terms/");
private static final Namespace OAI_NS = Namespace.getNamespace("http://www.openarchives.org/OAI/2.0/");
@Autowired(required = true) @Autowired(required = true)
protected HarvestedCollectionDAO harvestedCollectionDAO; protected HarvestedCollectionDAO harvestedCollectionDAO;
@@ -156,5 +172,94 @@ public class HarvestedCollectionServiceImpl implements HarvestedCollectionServic
return 0 < harvestedCollectionDAO.count(context); return 0 < harvestedCollectionDAO.count(context);
} }
/**
* Verify the existence of an OAI server with the specified set and
* supporting the provided metadata formats.
*
* @param oaiSource the address of the OAI-PMH provider
* @param oaiSetId OAI set identifier
* @param metaPrefix OAI metadataPrefix
* @param testORE whether the method should also check the PMH provider for ORE support
* @return list of errors encountered during verification. Empty list indicates a "success" condition.
*/
public List<String> verifyOAIharvester(String oaiSource,
String oaiSetId, String metaPrefix, boolean testORE) {
List<String> errorSet = new ArrayList<String>();
// First, see if we can contact the target server at all.
try {
new Identify(oaiSource);
} catch (Exception ex) {
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached.");
return errorSet;
}
// Next, make sure the metadata we need is supported by the target server
Namespace DMD_NS = OAIHarvester.getDMDNamespace(metaPrefix);
if (null == DMD_NS) {
errorSet.add(OAI_DMD_ERROR + ": " + metaPrefix);
return errorSet;
}
String OREOAIPrefix = null;
String DMDOAIPrefix = null;
try {
OREOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, OAIHarvester.getORENamespace().getURI());
DMDOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, DMD_NS.getURI());
} catch (Exception ex) {
errorSet.add(OAI_ADDRESS_ERROR
+ ": OAI did not respond to ListMetadataFormats query ("
+ ORE_NS.getPrefix() + ":" + OREOAIPrefix + " ; "
+ DMD_NS.getPrefix() + ":" + DMDOAIPrefix + "): "
+ ex.getMessage());
return errorSet;
}
if (testORE && OREOAIPrefix == null) {
errorSet.add(OAI_ORE_ERROR + ": The OAI server does not support ORE dissemination");
}
if (DMDOAIPrefix == null) {
errorSet.add(OAI_DMD_ERROR + ": The OAI server does not support dissemination in this format");
}
// Now scan the sets and make sure the one supplied is in the list
boolean foundSet = false;
try {
//If we do not want to harvest from one set, then skip this.
if (!"all".equals(oaiSetId)) {
ListIdentifiers ls = new ListIdentifiers(oaiSource, null, null, oaiSetId, DMDOAIPrefix);
// The only error we can really get here is "noSetHierarchy"
if (ls.getErrors() != null && ls.getErrors().getLength() > 0) {
for (int i = 0; i < ls.getErrors().getLength(); i++) {
String errorCode = ls.getErrors().item(i).getAttributes().getNamedItem("code").getTextContent();
errorSet.add(
OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec (" +
errorCode + ")");
}
} else {
// Drilling down to /OAI-PMH/ListSets/set
DOMBuilder db = new DOMBuilder();
Document reply = db.build(ls.getDocument());
Element root = reply.getRootElement();
//Check if we can find items, if so this indicates that we have children and our sets exist
foundSet = 0 < root.getChild("ListIdentifiers", OAI_NS).getChildren().size();
if (!foundSet) {
errorSet.add(OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec");
}
}
}
} catch (RuntimeException re) {
throw re;
} catch (Exception e) {
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached");
return errorSet;
}
return errorSet;
}
} }

View File

@@ -17,10 +17,14 @@ import java.sql.SQLException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
@@ -28,7 +32,6 @@ import javax.xml.transform.TransformerException;
import ORG.oclc.oai.harvester2.verb.GetRecord; import ORG.oclc.oai.harvester2.verb.GetRecord;
import ORG.oclc.oai.harvester2.verb.Identify; import ORG.oclc.oai.harvester2.verb.Identify;
import ORG.oclc.oai.harvester2.verb.ListIdentifiers;
import ORG.oclc.oai.harvester2.verb.ListMetadataFormats; import ORG.oclc.oai.harvester2.verb.ListMetadataFormats;
import ORG.oclc.oai.harvester2.verb.ListRecords; import ORG.oclc.oai.harvester2.verb.ListRecords;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -102,7 +105,7 @@ public class OAIHarvester {
protected BitstreamFormatService bitstreamFormatService; protected BitstreamFormatService bitstreamFormatService;
protected BundleService bundleService; protected BundleService bundleService;
protected CollectionService collectionService; protected CollectionService collectionService;
protected HarvestedCollectionService harvestedCollection; protected HarvestedCollectionService harvestedCollectionService;
protected InstallItemService installItemService; protected InstallItemService installItemService;
protected ItemService itemService; protected ItemService itemService;
protected HandleService handleService; protected HandleService handleService;
@@ -140,7 +143,7 @@ public class OAIHarvester {
bundleService = ContentServiceFactory.getInstance().getBundleService(); bundleService = ContentServiceFactory.getInstance().getBundleService();
collectionService = ContentServiceFactory.getInstance().getCollectionService(); collectionService = ContentServiceFactory.getInstance().getCollectionService();
handleService = HandleServiceFactory.getInstance().getHandleService(); handleService = HandleServiceFactory.getInstance().getHandleService();
harvestedCollection = HarvestServiceFactory.getInstance().getHarvestedCollectionService(); harvestedCollectionService = HarvestServiceFactory.getInstance().getHarvestedCollectionService();
harvestedItemService = HarvestServiceFactory.getInstance().getHarvestedItemService(); harvestedItemService = HarvestServiceFactory.getInstance().getHarvestedItemService();
itemService = ContentServiceFactory.getInstance().getItemService(); itemService = ContentServiceFactory.getInstance().getItemService();
installItemService = ContentServiceFactory.getInstance().getInstallItemService(); installItemService = ContentServiceFactory.getInstance().getInstallItemService();
@@ -150,7 +153,6 @@ public class OAIHarvester {
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
if (dso.getType() != Constants.COLLECTION) { if (dso.getType() != Constants.COLLECTION) {
throw new HarvestingException("OAIHarvester can only harvest collections"); throw new HarvestingException("OAIHarvester can only harvest collections");
} }
@@ -159,7 +161,7 @@ public class OAIHarvester {
targetCollection = (Collection) dso; targetCollection = (Collection) dso;
harvestRow = hc; harvestRow = hc;
if (harvestRow == null || !harvestedCollection.isHarvestable(harvestRow)) { if (harvestRow == null || !harvestedCollectionService.isHarvestable(harvestRow)) {
throw new HarvestingException("Provided collection is not set up for harvesting"); throw new HarvestingException("Provided collection is not set up for harvesting");
} }
@@ -188,7 +190,7 @@ public class OAIHarvester {
* *
* @return Namespace of the supported ORE format. Returns null if not found. * @return Namespace of the supported ORE format. Returns null if not found.
*/ */
private static Namespace getORENamespace() { public static Namespace getORENamespace() {
String ORESerializationString = null; String ORESerializationString = null;
String ORESeialKey = null; String ORESeialKey = null;
String oreString = "oai.harvester.oreSerializationFormat"; String oreString = "oai.harvester.oreSerializationFormat";
@@ -213,7 +215,7 @@ public class OAIHarvester {
* @param metadataKey * @param metadataKey
* @return Namespace of the designated metadata format. Returns null of not found. * @return Namespace of the designated metadata format. Returns null of not found.
*/ */
private static Namespace getDMDNamespace(String metadataKey) { public static Namespace getDMDNamespace(String metadataKey) {
String metadataString = null; String metadataString = null;
String metaString = "oai.harvester.metadataformats"; String metaString = "oai.harvester.metadataformats";
@@ -313,7 +315,7 @@ public class OAIHarvester {
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_BUSY); harvestRow.setHarvestStatus(HarvestedCollection.STATUS_BUSY);
harvestRow.setHarvestMessage("Collection harvesting is initializing..."); harvestRow.setHarvestMessage("Collection harvesting is initializing...");
harvestRow.setHarvestStartTime(startTime); harvestRow.setHarvestStartTime(startTime);
harvestedCollection.update(ourContext, harvestRow); harvestedCollectionService.update(ourContext, harvestRow);
intermediateCommit(); intermediateCommit();
// expiration timer starts // expiration timer starts
@@ -354,7 +356,7 @@ public class OAIHarvester {
harvestRow.setHarvestStartTime(new Date()); harvestRow.setHarvestStartTime(new Date());
harvestRow.setHarvestMessage("OAI server did not contain any updates"); harvestRow.setHarvestMessage("OAI server did not contain any updates");
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_READY); harvestRow.setHarvestStatus(HarvestedCollection.STATUS_READY);
harvestedCollection.update(ourContext, harvestRow); harvestedCollectionService.update(ourContext, harvestRow);
return; return;
} else { } else {
throw new HarvestingException(errorSet.toString()); throw new HarvestingException(errorSet.toString());
@@ -411,7 +413,7 @@ public class OAIHarvester {
harvestRow.setHarvestMessage(String harvestRow.setHarvestMessage(String
.format("Collection is currently being harvested (item %d of %d)", .format("Collection is currently being harvested (item %d of %d)",
currentRecord, totalListSize)); currentRecord, totalListSize));
harvestedCollection.update(ourContext, harvestRow); harvestedCollectionService.update(ourContext, harvestRow);
} finally { } finally {
//In case of an exception, make sure to restore our authentication state to the previous state //In case of an exception, make sure to restore our authentication state to the previous state
ourContext.restoreAuthSystemState(); ourContext.restoreAuthSystemState();
@@ -429,19 +431,19 @@ public class OAIHarvester {
alertAdmin(HarvestedCollection.STATUS_OAI_ERROR, hex); alertAdmin(HarvestedCollection.STATUS_OAI_ERROR, hex);
} }
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_OAI_ERROR); harvestRow.setHarvestStatus(HarvestedCollection.STATUS_OAI_ERROR);
harvestedCollection.update(ourContext, harvestRow); harvestedCollectionService.update(ourContext, harvestRow);
ourContext.complete(); ourContext.complete();
return; return;
} catch (Exception ex) { } catch (Exception ex) {
harvestRow.setHarvestMessage("Unknown error occurred while generating an OAI response"); harvestRow.setHarvestMessage("Unknown error occurred while generating an OAI response");
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_UNKNOWN_ERROR); harvestRow.setHarvestStatus(HarvestedCollection.STATUS_UNKNOWN_ERROR);
harvestedCollection.update(ourContext, harvestRow); harvestedCollectionService.update(ourContext, harvestRow);
alertAdmin(HarvestedCollection.STATUS_UNKNOWN_ERROR, ex); alertAdmin(HarvestedCollection.STATUS_UNKNOWN_ERROR, ex);
log.error("Error occurred while generating an OAI response: " + ex.getMessage() + " " + ex.getCause(), ex); log.error("Error occurred while generating an OAI response: " + ex.getMessage() + " " + ex.getCause(), ex);
ourContext.complete(); ourContext.complete();
return; return;
} finally { } finally {
harvestedCollection.update(ourContext, harvestRow); harvestedCollectionService.update(ourContext, harvestRow);
ourContext.turnOffAuthorisationSystem(); ourContext.turnOffAuthorisationSystem();
collectionService.update(ourContext, targetCollection); collectionService.update(ourContext, targetCollection);
ourContext.restoreAuthSystemState(); ourContext.restoreAuthSystemState();
@@ -456,7 +458,7 @@ public class OAIHarvester {
log.info( log.info(
"Harvest from " + oaiSource + " successful. The process took " + timeTaken + " milliseconds. Harvested " "Harvest from " + oaiSource + " successful. The process took " + timeTaken + " milliseconds. Harvested "
+ currentRecord + " items."); + currentRecord + " items.");
harvestedCollection.update(ourContext, harvestRow); harvestedCollectionService.update(ourContext, harvestRow);
ourContext.setMode(originalMode); ourContext.setMode(originalMode);
} }
@@ -900,94 +902,44 @@ public class OAIHarvester {
String oaiSetId = harvestRow.getOaiSetId(); String oaiSetId = harvestRow.getOaiSetId();
String metaPrefix = harvestRow.getHarvestMetadataConfig(); String metaPrefix = harvestRow.getHarvestMetadataConfig();
return verifyOAIharvester(oaiSource, oaiSetId, metaPrefix, true); return harvestedCollectionService.verifyOAIharvester(oaiSource, oaiSetId, metaPrefix, true);
} }
/** /**
* Verify the existence of an OAI server with the specified set and * Return all available metadata formats
* supporting the provided metadata formats.
* *
* @param oaiSource the address of the OAI-PMH provider * @return a list containing a map for each supported metadata format
* @param oaiSetId OAI set identifier
* @param metaPrefix OAI metadataPrefix
* @param testORE whether the method should also check the PMH provider for ORE support
* @return list of errors encountered during verification. Empty list indicates a "success" condition.
*/ */
public static List<String> verifyOAIharvester(String oaiSource, public static List<Map<String,String>> getAvailableMetadataFormats() {
String oaiSetId, String metaPrefix, boolean testORE) { List<Map<String,String>> configs = new ArrayList<>();
List<String> errorSet = new ArrayList<String>(); String metaString = "oai.harvester.metadataformats.";
Enumeration pe = Collections.enumeration(
DSpaceServicesFactory.getInstance().getConfigurationService()
.getPropertyKeys("oai.harvester.metadataformats")
);
while (pe.hasMoreElements()) {
String key = (String) pe.nextElement();
String metadataString = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty(key);
// First, see if we can contact the target server at all. String id = key.substring(metaString.length());
try { String label;
new Identify(oaiSource); String namespace = "";
} catch (Exception ex) {
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached.");
return errorSet;
}
// Next, make sure the metadata we need is supported by the target server if (metadataString.indexOf(',') != -1) {
Namespace DMD_NS = OAIHarvester.getDMDNamespace(metaPrefix); label = metadataString.substring(metadataString.indexOf(',') + 2);
if (null == DMD_NS) { namespace = metadataString.substring(0, metadataString.indexOf(','));
errorSet.add(OAI_DMD_ERROR + ": " + metaPrefix); } else {
return errorSet; label = id + "(" + metadataString + ")";
}
String OREOAIPrefix = null;
String DMDOAIPrefix = null;
try {
OREOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, getORENamespace().getURI());
DMDOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, DMD_NS.getURI());
} catch (Exception ex) {
errorSet.add(OAI_ADDRESS_ERROR
+ ": OAI did not respond to ListMetadataFormats query ("
+ ORE_NS.getPrefix() + ":" + OREOAIPrefix + " ; "
+ DMD_NS.getPrefix() + ":" + DMDOAIPrefix + "): "
+ ex.getMessage());
return errorSet;
}
if (testORE && OREOAIPrefix == null) {
errorSet.add(OAI_ORE_ERROR + ": The OAI server does not support ORE dissemination");
}
if (DMDOAIPrefix == null) {
errorSet.add(OAI_DMD_ERROR + ": The OAI server does not support dissemination in this format");
}
// Now scan the sets and make sure the one supplied is in the list
boolean foundSet = false;
try {
//If we do not want to harvest from one set, then skip this.
if (!"all".equals(oaiSetId)) {
ListIdentifiers ls = new ListIdentifiers(oaiSource, null, null, oaiSetId, DMDOAIPrefix);
// The only error we can really get here is "noSetHierarchy"
if (ls.getErrors() != null && ls.getErrors().getLength() > 0) {
for (int i = 0; i < ls.getErrors().getLength(); i++) {
String errorCode = ls.getErrors().item(i).getAttributes().getNamedItem("code").getTextContent();
errorSet.add(
OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec (" +
errorCode + ")");
}
} else {
// Drilling down to /OAI-PMH/ListSets/set
Document reply = db.build(ls.getDocument());
Element root = reply.getRootElement();
//Check if we can find items, if so this indicates that we have children and our sets exist
foundSet = 0 < root.getChild("ListIdentifiers", OAI_NS).getChildren().size();
if (!foundSet) {
errorSet.add(OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec");
}
}
} }
} catch (RuntimeException re) {
throw re; Map<String,String> config = new HashMap<>();
} catch (Exception e) { config.put("id", id);
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached"); config.put("label", label);
return errorSet; config.put("namespace", namespace);
configs.add(config);
} }
return errorSet; return configs;
} }
} }

View File

@@ -137,4 +137,15 @@ public interface HarvestedCollectionService {
public void update(Context context, HarvestedCollection harvestedCollection) throws SQLException; public void update(Context context, HarvestedCollection harvestedCollection) throws SQLException;
public boolean exists(Context context) throws SQLException; public boolean exists(Context context) throws SQLException;
/**
* Test the given harvest settings
* @param oaiSource the address of the OAI-PMH provider
* @param oaiSetId OAI set identifier
* @param metaPrefix OAI metadataPrefix
* @param testORE whether the method should also check the PMH provider for ORE support
* @return list of errors encountered during verification. An empty list indicates a "success" condition.
*/
public List<String> verifyOAIharvester(String oaiSource,
String oaiSetId, String metaPrefix, boolean testORE);
} }

View File

@@ -0,0 +1,18 @@
--
-- 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/
--
-----------------------------------------------------------------------------------
-- Create columns leftwardValue and rightwardValue in table relationship
-- Rename columns left_label and right_label to leftward_type and rightward_type
-----------------------------------------------------------------------------------
ALTER TABLE relationship ADD leftward_value VARCHAR;
ALTER TABLE relationship ADD rightward_value VARCHAR;
ALTER TABLE relationship_type ALTER COLUMN left_label RENAME TO leftward_type;
ALTER TABLE relationship_type ALTER COLUMN right_label RENAME TO rightward_type;

View File

@@ -0,0 +1,18 @@
--
-- 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/
--
-----------------------------------------------------------------------------------
-- Create columns leftwardValue and rightwardValue in table relationship
-- Rename columns left_label and right_label to leftward_type and rightward_type
-----------------------------------------------------------------------------------
ALTER TABLE relationship ADD leftward_value VARCHAR;
ALTER TABLE relationship ADD rightward_value VARCHAR;
ALTER TABLE relationship_type RENAME left_label TO leftward_type;
ALTER TABLE relationship_type RENAME right_label TO rightward_type;

View File

@@ -0,0 +1,18 @@
--
-- 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/
--
-----------------------------------------------------------------------------------
-- Create columns leftwardValue and rightwardValue in table relationship
-- Rename columns left_label and right_label to leftward_type and rightward_type
-----------------------------------------------------------------------------------
ALTER TABLE relationship ADD leftward_value VARCHAR;
ALTER TABLE relationship ADD rightward_value VARCHAR;
ALTER TABLE relationship_type RENAME COLUMN left_label TO leftward_type;
ALTER TABLE relationship_type RENAME COLUMN right_label TO rightward_type;

View File

@@ -5,8 +5,8 @@
<type> <type>
<leftType>Publication</leftType> <leftType>Publication</leftType>
<rightType>Person</rightType> <rightType>Person</rightType>
<leftLabel>isAuthorOfPublication</leftLabel> <leftwardType>isAuthorOfPublication</leftwardType>
<rightLabel>isPublicationOfAuthor</rightLabel> <rightwardType>isPublicationOfAuthor</rightwardType>
<leftCardinality> <leftCardinality>
<min>10</min> <min>10</min>
</leftCardinality> </leftCardinality>
@@ -17,8 +17,8 @@
<type> <type>
<leftType>Publication</leftType> <leftType>Publication</leftType>
<rightType>Project</rightType> <rightType>Project</rightType>
<leftLabel>isProjectOfPublication</leftLabel> <leftwardType>isProjectOfPublication</leftwardType>
<rightLabel>isPublicationOfProject</rightLabel> <rightwardType>isPublicationOfProject</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -29,8 +29,8 @@
<type> <type>
<leftType>Publication</leftType> <leftType>Publication</leftType>
<rightType>OrgUnit</rightType> <rightType>OrgUnit</rightType>
<leftLabel>isOrgUnitOfPublication</leftLabel> <leftwardType>isOrgUnitOfPublication</leftwardType>
<rightLabel>isPublicationOfOrgUnit</rightLabel> <rightwardType>isPublicationOfOrgUnit</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -41,8 +41,8 @@
<type> <type>
<leftType>Person</leftType> <leftType>Person</leftType>
<rightType>Project</rightType> <rightType>Project</rightType>
<leftLabel>isProjectOfPerson</leftLabel> <leftwardType>isProjectOfPerson</leftwardType>
<rightLabel>isPersonOfProject</rightLabel> <rightwardType>isPersonOfProject</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -53,8 +53,8 @@
<type> <type>
<leftType>Person</leftType> <leftType>Person</leftType>
<rightType>OrgUnit</rightType> <rightType>OrgUnit</rightType>
<leftLabel>isOrgUnitOfPerson</leftLabel> <leftwardType>isOrgUnitOfPerson</leftwardType>
<rightLabel>isPersonOfOrgUnit</rightLabel> <rightwardType>isPersonOfOrgUnit</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -65,8 +65,8 @@
<type> <type>
<leftType>Project</leftType> <leftType>Project</leftType>
<rightType>OrgUnit</rightType> <rightType>OrgUnit</rightType>
<leftLabel>isOrgUnitOfProject</leftLabel> <leftwardType>isOrgUnitOfProject</leftwardType>
<rightLabel>isProjectOfOrgUnit</rightLabel> <rightwardType>isProjectOfOrgUnit</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -77,8 +77,8 @@
<type> <type>
<leftType>Journal</leftType> <leftType>Journal</leftType>
<rightType>JournalVolume</rightType> <rightType>JournalVolume</rightType>
<leftLabel>isVolumeOfJournal</leftLabel> <leftwardType>isVolumeOfJournal</leftwardType>
<rightLabel>isJournalOfVolume</rightLabel> <rightwardType>isJournalOfVolume</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -89,8 +89,8 @@
<type> <type>
<leftType>JournalVolume</leftType> <leftType>JournalVolume</leftType>
<rightType>JournalIssue</rightType> <rightType>JournalIssue</rightType>
<leftLabel>isIssueOfJournalVolume</leftLabel> <leftwardType>isIssueOfJournalVolume</leftwardType>
<rightLabel>isJournalVolumeOfIssue</rightLabel> <rightwardType>isJournalVolumeOfIssue</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -102,8 +102,8 @@
<type> <type>
<leftType>Publication</leftType> <leftType>Publication</leftType>
<rightType>OrgUnit</rightType> <rightType>OrgUnit</rightType>
<leftLabel>isAuthorOfPublication</leftLabel> <leftwardType>isAuthorOfPublication</leftwardType>
<rightLabel>isPublicationOfAuthor</rightLabel> <rightwardType>isPublicationOfAuthor</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -114,8 +114,8 @@
<type> <type>
<leftType>JournalIssue</leftType> <leftType>JournalIssue</leftType>
<rightType>Publication</rightType> <rightType>Publication</rightType>
<leftLabel>isPublicationOfJournalIssue</leftLabel> <leftwardType>isPublicationOfJournalIssue</leftwardType>
<rightLabel>isJournalIssueOfPublication</rightLabel> <rightwardType>isJournalIssueOfPublication</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>

View File

@@ -2,11 +2,11 @@
<!ELEMENT relationships (type)*> <!ELEMENT relationships (type)*>
<!ELEMENT type (leftType|rightType|leftLabel|rightLabel|leftCardinality|rightCardinality)*> <!ELEMENT type (leftType|rightType|leftwardType|rightwardType|leftCardinality|rightCardinality)*>
<!ELEMENT leftType (#PCDATA)> <!ELEMENT leftType (#PCDATA)>
<!ELEMENT rightType (#PCDATA)> <!ELEMENT rightType (#PCDATA)>
<!ELEMENT leftLabel (#PCDATA)> <!ELEMENT leftwardType (#PCDATA)>
<!ELEMENT rightLabel (#PCDATA)> <!ELEMENT rightwardType (#PCDATA)>
<!ELEMENT leftCardinality (min|max)*> <!ELEMENT leftCardinality (min|max)*>
<!ELEMENT min (#PCDATA)> <!ELEMENT min (#PCDATA)>
<!ELEMENT rightCardinality (min|max)*> <!ELEMENT rightCardinality (min|max)*>

View File

@@ -5,8 +5,8 @@
<type> <type>
<leftType>Publication</leftType> <leftType>Publication</leftType>
<rightType>Person</rightType> <rightType>Person</rightType>
<leftLabel>isAuthorOfPublication</leftLabel> <leftwardType>isAuthorOfPublication</leftwardType>
<rightLabel>isPublicationOfAuthor</rightLabel> <rightwardType>isPublicationOfAuthor</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -17,8 +17,8 @@
<type> <type>
<leftType>Publication</leftType> <leftType>Publication</leftType>
<rightType>Project</rightType> <rightType>Project</rightType>
<leftLabel>isProjectOfPublication</leftLabel> <leftwardType>isProjectOfPublication</leftwardType>
<rightLabel>isPublicationOfProject</rightLabel> <rightwardType>isPublicationOfProject</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -29,8 +29,8 @@
<type> <type>
<leftType>Publication</leftType> <leftType>Publication</leftType>
<rightType>OrgUnit</rightType> <rightType>OrgUnit</rightType>
<leftLabel>isOrgUnitOfPublication</leftLabel> <leftwardType>isOrgUnitOfPublication</leftwardType>
<rightLabel>isPublicationOfOrgUnit</rightLabel> <rightwardType>isPublicationOfOrgUnit</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -41,8 +41,8 @@
<type> <type>
<leftType>Person</leftType> <leftType>Person</leftType>
<rightType>Project</rightType> <rightType>Project</rightType>
<leftLabel>isProjectOfPerson</leftLabel> <leftwardType>isProjectOfPerson</leftwardType>
<rightLabel>isPersonOfProject</rightLabel> <rightwardType>isPersonOfProject</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -53,8 +53,8 @@
<type> <type>
<leftType>Person</leftType> <leftType>Person</leftType>
<rightType>OrgUnit</rightType> <rightType>OrgUnit</rightType>
<leftLabel>isOrgUnitOfPerson</leftLabel> <leftwardType>isOrgUnitOfPerson</leftwardType>
<rightLabel>isPersonOfOrgUnit</rightLabel> <rightwardType>isPersonOfOrgUnit</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -65,8 +65,8 @@
<type> <type>
<leftType>Project</leftType> <leftType>Project</leftType>
<rightType>OrgUnit</rightType> <rightType>OrgUnit</rightType>
<leftLabel>isOrgUnitOfProject</leftLabel> <leftwardType>isOrgUnitOfProject</leftwardType>
<rightLabel>isProjectOfOrgUnit</rightLabel> <rightwardType>isProjectOfOrgUnit</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -77,8 +77,8 @@
<type> <type>
<leftType>Journal</leftType> <leftType>Journal</leftType>
<rightType>JournalVolume</rightType> <rightType>JournalVolume</rightType>
<leftLabel>isVolumeOfJournal</leftLabel> <leftwardType>isVolumeOfJournal</leftwardType>
<rightLabel>isJournalOfVolume</rightLabel> <rightwardType>isJournalOfVolume</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -89,8 +89,8 @@
<type> <type>
<leftType>JournalVolume</leftType> <leftType>JournalVolume</leftType>
<rightType>JournalIssue</rightType> <rightType>JournalIssue</rightType>
<leftLabel>isIssueOfJournalVolume</leftLabel> <leftwardType>isIssueOfJournalVolume</leftwardType>
<rightLabel>isJournalVolumeOfIssue</rightLabel> <rightwardType>isJournalVolumeOfIssue</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -102,8 +102,8 @@
<type> <type>
<leftType>Publication</leftType> <leftType>Publication</leftType>
<rightType>OrgUnit</rightType> <rightType>OrgUnit</rightType>
<leftLabel>isAuthorOfPublication</leftLabel> <leftwardType>isAuthorOfPublication</leftwardType>
<rightLabel>isPublicationOfAuthor</rightLabel> <rightwardType>isPublicationOfAuthor</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>
@@ -114,8 +114,8 @@
<type> <type>
<leftType>JournalIssue</leftType> <leftType>JournalIssue</leftType>
<rightType>Publication</rightType> <rightType>Publication</rightType>
<leftLabel>isPublicationOfJournalIssue</leftLabel> <leftwardType>isPublicationOfJournalIssue</leftwardType>
<rightLabel>isJournalIssueOfPublication</rightLabel> <rightwardType>isJournalIssueOfPublication</rightwardType>
<leftCardinality> <leftCardinality>
<min>0</min> <min>0</min>
</leftCardinality> </leftCardinality>

View File

@@ -25,6 +25,9 @@
# SERVER CONFIGURATION # # SERVER CONFIGURATION #
########################## ##########################
# Spring boot test by default mock the server on the localhost (80)
dspace.baseUrl = http://localhost
# DSpace installation directory. # DSpace installation directory.
# This is the location where you want to install DSpace. # This is the location where you want to install DSpace.
# Windows note: Please remember to use forward slashes for all paths (e.g. C:/dspace) # Windows note: Please remember to use forward slashes for all paths (e.g. C:/dspace)

View File

@@ -23,6 +23,10 @@
<alias name="org.dspace.discovery.SearchService" alias="org.dspace.discovery.IndexingService"/> <alias name="org.dspace.discovery.SearchService" alias="org.dspace.discovery.IndexingService"/>
<!-- These beans have been added so that we can mock our AuthoritySearchService in the tests-->
<bean class="org.dspace.authority.MockAuthoritySolrServiceImpl" id="org.dspace.authority.AuthoritySearchService"/>
<alias name="org.dspace.authority.AuthoritySearchService" alias="org.dspace.authority.indexer.AuthorityIndexingService"/>
<!--<bean class="org.dspace.discovery.SolrServiceIndexOutputPlugin" id="solrServiceIndexOutputPlugin"/>--> <!--<bean class="org.dspace.discovery.SolrServiceIndexOutputPlugin" id="solrServiceIndexOutputPlugin"/>-->
<!-- Statistics services are both lazy loaded (by name), as you are likely just using ONE of them and not both --> <!-- Statistics services are both lazy loaded (by name), as you are likely just using ONE of them and not both -->

View File

@@ -0,0 +1,24 @@
/**
* 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.authority;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
/**
* This class has been created so that we can mock our AuthoritySolrSeviceImpl
*/
@Service
public class MockAuthoritySolrServiceImpl extends AuthoritySolrServiceImpl implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
//We don't use SOLR in the tests of this module
solr = null;
}
}

View File

@@ -135,7 +135,7 @@ public class EntityServiceImplTest {
} }
@Test @Test
public void testGetRelationsByLabel() throws Exception { public void testGetRelationsByTypeName() throws Exception {
// Declare objects utilized in unit test // Declare objects utilized in unit test
Relationship relationship = mock(Relationship.class); Relationship relationship = mock(Relationship.class);
RelationshipType relationshipType = mock(RelationshipType.class); RelationshipType relationshipType = mock(RelationshipType.class);
@@ -145,15 +145,16 @@ public class EntityServiceImplTest {
List<Relationship> relationshipList = new ArrayList<>(); List<Relationship> relationshipList = new ArrayList<>();
relationshipList.add(relationship); relationshipList.add(relationship);
// Mock the state of objects utilized in getRelationsByLabel() to meet the success criteria of an invocation // Mock the state of objects utilized in getRelationsByType() to meet the success criteria of an invocation
when(relationshipService.findAll(context)).thenReturn(relationshipList); when(relationshipService.findAll(context, -1, -1)).thenReturn(relationshipList);
when(relationship.getRelationshipType()).thenReturn(relationshipType); when(relationship.getRelationshipType()).thenReturn(relationshipType);
when(relationshipType.getLeftLabel()).thenReturn("leftLabel"); when(relationshipType.getLeftwardType()).thenReturn("leftwardType");
when(relationshipType.getRightLabel()).thenReturn("rightLabel"); when(relationshipType.getRightwardType()).thenReturn("rightwardType");
when(relationshipService.findByTypeName(context, "leftwardType", -1, -1)).thenReturn(relationshipList);
// The relation(s) reported from our defined label should match our relationshipList // The relation(s) reported from our defined type should match our relationshipList
assertEquals("TestGetRelationsByLabel 0", relationshipList, assertEquals("TestGetRelationsByLabel 0", relationshipList,
entityService.getRelationsByLabel(context, "leftLabel")); entityService.getRelationsByTypeName(context, "leftwardType"));
} }
@Test @Test
@@ -178,14 +179,16 @@ public class EntityServiceImplTest {
when(metadataValue.getValue()).thenReturn("testType"); when(metadataValue.getValue()).thenReturn("testType");
when(entity.getItem()).thenReturn(item); when(entity.getItem()).thenReturn(item);
when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY)).thenReturn(list); when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY)).thenReturn(list);
when(relationshipTypeDAO.findAll(context, RelationshipType.class)).thenReturn(relationshipTypeList); when(relationshipTypeDAO.findAll(context, RelationshipType.class, -1, -1)).thenReturn(relationshipTypeList);
when(relationshipTypeService.findAll(context)).thenReturn(relationshipTypeList); when(relationshipTypeService.findAll(context, -1, -1)).thenReturn(relationshipTypeList);
when(relationshipType.getLeftType()).thenReturn(leftType); when(relationshipType.getLeftType()).thenReturn(leftType);
when(relationshipType.getRightType()).thenReturn(rightType); when(relationshipType.getRightType()).thenReturn(rightType);
when(entityTypeService.findByEntityType(context, "value")).thenReturn(leftType); when(entityTypeService.findByEntityType(context, "value")).thenReturn(leftType);
when(leftType.getID()).thenReturn(0); when(leftType.getID()).thenReturn(0);
when(rightType.getID()).thenReturn(1); when(rightType.getID()).thenReturn(1);
when(entityService.getType(context, entity)).thenReturn(leftType); // Mock when(entityService.getType(context, entity)).thenReturn(leftType); // Mock
when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), -1, -1))
.thenReturn(relationshipTypeList);
// The relation(s) reported from our mocked Entity should match our relationshipList // The relation(s) reported from our mocked Entity should match our relationshipList
assertEquals("TestGetAllRelationshipTypes 0", relationshipTypeList, assertEquals("TestGetAllRelationshipTypes 0", relationshipTypeList,
@@ -212,10 +215,12 @@ public class EntityServiceImplTest {
when(itemService.getMetadata(any(), any(), any(), any(), any())).thenReturn(metsList); when(itemService.getMetadata(any(), any(), any(), any(), any())).thenReturn(metsList);
when(entity.getItem()).thenReturn(item); when(entity.getItem()).thenReturn(item);
when(entityType.getID()).thenReturn(0); when(entityType.getID()).thenReturn(0);
when(relationshipTypeService.findAll(any())).thenReturn(relationshipTypeList); when(relationshipTypeService.findAll(context, -1, -1)).thenReturn(relationshipTypeList);
when(relationshipType.getLeftType()).thenReturn(entityType); when(relationshipType.getLeftType()).thenReturn(entityType);
when(entityService.getType(context, entity)).thenReturn(entityType); when(entityService.getType(context, entity)).thenReturn(entityType);
when(entityTypeService.findByEntityType(any(), any())).thenReturn(entityType); when(entityTypeService.findByEntityType(any(), any())).thenReturn(entityType);
when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), true, -1, -1))
.thenReturn(relationshipTypeList);
// The left relationshipType(s) reported from our mocked Entity should match our relationshipList // The left relationshipType(s) reported from our mocked Entity should match our relationshipList
assertEquals("TestGetLeftRelationshipTypes 0", relationshipTypeList, assertEquals("TestGetLeftRelationshipTypes 0", relationshipTypeList,
@@ -242,10 +247,12 @@ public class EntityServiceImplTest {
when(itemService.getMetadata(any(), any(), any(), any(), any())).thenReturn(metsList); when(itemService.getMetadata(any(), any(), any(), any(), any())).thenReturn(metsList);
when(entity.getItem()).thenReturn(item); when(entity.getItem()).thenReturn(item);
when(entityType.getID()).thenReturn(0); when(entityType.getID()).thenReturn(0);
when(relationshipTypeService.findAll(any())).thenReturn(relationshipTypeList); when(relationshipTypeService.findAll(context, -1, -1)).thenReturn(relationshipTypeList);
when(relationshipType.getRightType()).thenReturn(entityType); when(relationshipType.getRightType()).thenReturn(entityType);
when(entityService.getType(context, entity)).thenReturn(entityType); when(entityService.getType(context, entity)).thenReturn(entityType);
when(entityTypeService.findByEntityType(any(), any())).thenReturn(entityType); when(entityTypeService.findByEntityType(any(), any())).thenReturn(entityType);
when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), false, -1, -1))
.thenReturn(relationshipTypeList);
// The right relationshipType(s) reported from our mocked Entity should match our relationshipList // The right relationshipType(s) reported from our mocked Entity should match our relationshipList
assertEquals("TestGetRightRelationshipTypes 0", relationshipTypeList, assertEquals("TestGetRightRelationshipTypes 0", relationshipTypeList,
@@ -254,21 +261,23 @@ public class EntityServiceImplTest {
@Test @Test
public void testGetRelationshipTypesByLabel() throws Exception { public void testGetRelationshipTypesByTypeName() throws Exception {
// Declare objects utilized in unit test // Declare objects utilized in unit test
List<RelationshipType> list = new LinkedList<>(); List<RelationshipType> list = new LinkedList<>();
RelationshipType relationshipType = mock(RelationshipType.class); RelationshipType relationshipType = mock(RelationshipType.class);
list.add(relationshipType); list.add(relationshipType);
// Mock the state of objects utilized in getRelationshipTypesByLabel() // Mock the state of objects utilized in getRelationshipTypesByTypeName()
// to meet the success criteria of the invocation // to meet the success criteria of the invocation
when(relationshipTypeService.findAll(context)).thenReturn(list); when(relationshipTypeService.findAll(context, -1, -1)).thenReturn(list);
when(relationshipType.getLeftLabel()).thenReturn("leftLabel"); when(relationshipType.getLeftwardType()).thenReturn("leftwardType");
when(relationshipType.getRightLabel()).thenReturn("rightLabel"); when(relationshipType.getRightwardType()).thenReturn("rightwardType");
when(relationshipTypeService.findByLeftwardOrRightwardTypeName(context, "leftwardType", -1, -1))
.thenReturn(list);
// The RelationshipType(s) reported from our mocked Entity should match our list // The RelationshipType(s) reported from our mocked Entity should match our list
assertEquals("TestGetRelationshipTypesByLabel 0", list, assertEquals("TestGetRelationshipTypesByLabel 0", list,
entityService.getRelationshipTypesByLabel(context, "leftLabel")); entityService.getRelationshipTypesByTypeName(context, "leftwardType"));
} }

View File

@@ -0,0 +1,142 @@
/**
* 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.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.sql.SQLException;
import java.util.List;
import org.apache.logging.log4j.Logger;
import org.dspace.AbstractUnitTest;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
import org.dspace.content.service.EntityService;
import org.dspace.content.service.EntityTypeService;
import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.content.service.WorkspaceItemService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class RelationshipMetadataServiceTest extends AbstractUnitTest {
private static final Logger log = org.apache.logging.log4j.LogManager
.getLogger(RelationshipMetadataServiceTest.class);
protected RelationshipMetadataService relationshipMetadataService = ContentServiceFactory
.getInstance().getRelationshipMetadataService();
protected RelationshipService relationshipService = ContentServiceFactory.getInstance().getRelationshipService();
protected RelationshipTypeService relationshipTypeService = ContentServiceFactory.getInstance()
.getRelationshipTypeService();
protected EntityService entityService = ContentServiceFactory.getInstance().getEntityService();
protected EntityTypeService entityTypeService = ContentServiceFactory.getInstance().getEntityTypeService();
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
protected InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService();
protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
Item item;
Item authorItem;
/**
* This method will be run before every test as per @Before. It will
* initialize resources required for the tests.
*
* Other methods can be annotated with @Before here or in subclasses
* but no execution order is guaranteed
*/
@Before
@Override
public void init() {
super.init();
try {
context.turnOffAuthorisationSystem();
Community community = communityService.create(null, context);
Collection col = collectionService.create(context, community);
WorkspaceItem is = workspaceItemService.create(context, col, false);
WorkspaceItem authorIs = workspaceItemService.create(context, col, false);
item = installItemService.installItem(context, is);
authorItem = installItemService.installItem(context, authorIs);
context.restoreAuthSystemState();
} catch (AuthorizeException ex) {
log.error("Authorization Error in init", ex);
fail("Authorization Error in init: " + ex.getMessage());
} catch (SQLException ex) {
log.error("SQL Error in init", ex);
fail("SQL Error in init: " + ex.getMessage());
}
}
/**
* This method will be run after every test as per @After. It will
* clean resources initialized by the @Before methods.
*
* Other methods can be annotated with @After here or in subclasses
* but no execution order is guaranteed
*/
@After
@Override
public void destroy() {
context.abort();
super.destroy();
}
@Test
public void testGetRelationshipMetadata() throws Exception {
context.turnOffAuthorisationSystem();
itemService.addMetadata(context, item, "relationship", "type", null, null, "Publication");
itemService.addMetadata(context, authorItem, "relationship", "type", null, null, "Author");
itemService.addMetadata(context, authorItem, "person", "familyName", null, null, "familyName");
itemService.addMetadata(context, authorItem, "person", "givenName", null, null, "firstName");
EntityType publicationEntityType = entityTypeService.create(context, "Publication");
EntityType authorEntityType = entityTypeService.create(context, "Author");
RelationshipType isAuthorOfPublication = relationshipTypeService
.create(context, publicationEntityType, authorEntityType, "isAuthorOfPublication", "isPublicationOfAuthor",
null, null, null, null);
Relationship relationship = relationshipService.create(context, item, authorItem, isAuthorOfPublication, 0, 0);
context.restoreAuthSystemState();
List<MetadataValue> authorList = itemService.getMetadata(item, "dc", "contributor", "author", Item.ANY);
assertThat(authorList.size(), equalTo(1));
assertThat(authorList.get(0).getValue(), equalTo("familyName, firstName"));
List<MetadataValue> relationshipMetadataList = itemService
.getMetadata(item, "relation", "isAuthorOfPublication", null, Item.ANY);
assertThat(relationshipMetadataList.size(), equalTo(1));
assertThat(relationshipMetadataList.get(0).getValue(), equalTo(String.valueOf(authorItem.getID())));
List<RelationshipMetadataValue> list = relationshipMetadataService.getRelationshipMetadata(item, true);
assertThat(list.size(), equalTo(2));
assertThat(list.get(0).getValue(), equalTo("familyName, firstName"));
assertThat(list.get(0).getMetadataField().getMetadataSchema().getName(), equalTo("dc"));
assertThat(list.get(0).getMetadataField().getElement(), equalTo("contributor"));
assertThat(list.get(0).getMetadataField().getQualifier(), equalTo("author"));
assertThat(list.get(0).getAuthority(), equalTo("virtual::" + relationship.getID()));
assertThat(list.get(1).getValue(), equalTo(String.valueOf(authorItem.getID())));
assertThat(list.get(1).getMetadataField().getMetadataSchema().getName(), equalTo("relation"));
assertThat(list.get(1).getMetadataField().getElement(), equalTo("isAuthorOfPublication"));
assertThat(list.get(1).getAuthority(), equalTo("virtual::" + relationship.getID()));
}
}

View File

@@ -66,7 +66,7 @@ public class RelationshipServiceImplTest {
@Test @Test
public void testFindAll() throws Exception { public void testFindAll() throws Exception {
// Mock DAO to return our mocked relationshipsList // Mock DAO to return our mocked relationshipsList
when(relationshipDAO.findAll(context, Relationship.class)).thenReturn(relationshipsList); when(relationshipDAO.findAll(context, Relationship.class, -1, -1)).thenReturn(relationshipsList);
// The reported Relationship(s) should match our relationshipsList // The reported Relationship(s) should match our relationshipsList
assertEquals("TestFindAll 0", relationshipsList, relationshipService.findAll(context)); assertEquals("TestFindAll 0", relationshipsList, relationshipService.findAll(context));
} }
@@ -84,23 +84,22 @@ public class RelationshipServiceImplTest {
RelationshipType hasDog = new RelationshipType(); RelationshipType hasDog = new RelationshipType();
RelationshipType hasFather = new RelationshipType(); RelationshipType hasFather = new RelationshipType();
RelationshipType hasMother = new RelationshipType(); RelationshipType hasMother = new RelationshipType();
hasDog.setLeftLabel("hasDog"); hasDog.setLeftwardType("hasDog");
hasDog.setRightLabel("isDogOf"); hasDog.setRightwardType("isDogOf");
hasFather.setLeftLabel("hasFather"); hasFather.setLeftwardType("hasFather");
hasFather.setRightLabel("isFatherOf"); hasFather.setRightwardType("isFatherOf");
hasMother.setLeftLabel("hasMother"); hasMother.setLeftwardType("hasMother");
hasMother.setRightLabel("isMotherOf"); hasMother.setRightwardType("isMotherOf");
relationshipTest.add(getRelationship(cindy, spot, hasDog,0,0)); relationshipTest.add(getRelationship(cindy, spot, hasDog,0,0));
relationshipTest.add(getRelationship(cindy, jasper, hasDog,0,1)); relationshipTest.add(getRelationship(cindy, jasper, hasDog,0,1));
relationshipTest.add(getRelationship(cindy, hank, hasFather,0,0)); relationshipTest.add(getRelationship(cindy, hank, hasFather,0,0));
relationshipTest.add(getRelationship(fred, cindy, hasMother,0,0)); relationshipTest.add(getRelationship(fred, cindy, hasMother,0,0));
relationshipTest.add(getRelationship(bob, cindy, hasMother,1,0)); relationshipTest.add(getRelationship(bob, cindy, hasMother,1,0));
when(relationshipService.findByItem(context, cindy)).thenReturn(relationshipTest); when(relationshipService.findByItem(context, cindy, -1, -1)).thenReturn(relationshipTest);
when(relationshipDAO.findByItem(context, cindy)).thenReturn(relationshipTest);
// Mock the state of objects utilized in findByItem() to meet the success criteria of the invocation // Mock the state of objects utilized in findByItem() to meet the success criteria of the invocation
when(relationshipDAO.findByItem(context, cindy)).thenReturn(relationshipTest); when(relationshipDAO.findByItem(context, cindy, -1, -1)).thenReturn(relationshipTest);
List<Relationship> results = relationshipService.findByItem(context, cindy); List<Relationship> results = relationshipService.findByItem(context, cindy);
assertEquals("TestFindByItem 0", relationshipTest, results); assertEquals("TestFindByItem 0", relationshipTest, results);
@@ -194,8 +193,8 @@ public class RelationshipServiceImplTest {
EntityType rightEntityType = mock(EntityType.class); EntityType rightEntityType = mock(EntityType.class);
testRel.setLeftType(leftEntityType); testRel.setLeftType(leftEntityType);
testRel.setRightType(rightEntityType); testRel.setRightType(rightEntityType);
testRel.setLeftLabel("Entitylabel"); testRel.setLeftwardType("Entitylabel");
testRel.setRightLabel("Entitylabel"); testRel.setRightwardType("Entitylabel");
metsList.add(metVal); metsList.add(metVal);
relationship = getRelationship(leftItem, rightItem, testRel, 0,0); relationship = getRelationship(leftItem, rightItem, testRel, 0,0);
leftTypelist.add(relationship); leftTypelist.add(relationship);
@@ -247,8 +246,8 @@ public class RelationshipServiceImplTest {
EntityType rightEntityType = mock(EntityType.class); EntityType rightEntityType = mock(EntityType.class);
testRel.setLeftType(leftEntityType); testRel.setLeftType(leftEntityType);
testRel.setRightType(rightEntityType); testRel.setRightType(rightEntityType);
testRel.setLeftLabel("Entitylabel"); testRel.setLeftwardType("Entitylabel");
testRel.setRightLabel("Entitylabel"); testRel.setRightwardType("Entitylabel");
testRel.setLeftMinCardinality(0); testRel.setLeftMinCardinality(0);
testRel.setRightMinCardinality(0); testRel.setRightMinCardinality(0);
metsList.add(metVal); metsList.add(metVal);
@@ -271,6 +270,8 @@ public class RelationshipServiceImplTest {
when(metsList.get(0).getValue()).thenReturn("Entitylabel"); when(metsList.get(0).getValue()).thenReturn("Entitylabel");
when(relationshipService.findByItemAndRelationshipType(context, leftItem, testRel, true)) when(relationshipService.findByItemAndRelationshipType(context, leftItem, testRel, true))
.thenReturn(leftTypelist); .thenReturn(leftTypelist);
when(relationshipService.findByItemAndRelationshipType(context, rightItem, testRel, false))
.thenReturn(rightTypelist);
when(itemService.getMetadata(leftItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList); when(itemService.getMetadata(leftItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList);
when(itemService.getMetadata(rightItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList); when(itemService.getMetadata(rightItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList);
when(relationshipDAO.create(any(), any())).thenReturn(relationship); when(relationshipDAO.create(any(), any())).thenReturn(relationship);
@@ -299,8 +300,8 @@ public class RelationshipServiceImplTest {
EntityType rightEntityType = mock(EntityType.class); EntityType rightEntityType = mock(EntityType.class);
testRel.setLeftType(leftEntityType); testRel.setLeftType(leftEntityType);
testRel.setRightType(rightEntityType); testRel.setRightType(rightEntityType);
testRel.setLeftLabel("Entitylabel"); testRel.setLeftwardType("Entitylabel");
testRel.setRightLabel("Entitylabel"); testRel.setRightwardType("Entitylabel");
testRel.setLeftMinCardinality(0); testRel.setLeftMinCardinality(0);
testRel.setRightMinCardinality(0); testRel.setRightMinCardinality(0);
metsList.add(metVal); metsList.add(metVal);
@@ -321,6 +322,12 @@ public class RelationshipServiceImplTest {
Mockito.verify(relationshipDAO).save(context, relationship); Mockito.verify(relationshipDAO).save(context, relationship);
} }
@Test
public void testCountTotal() throws Exception {
when(relationshipDAO.countRows(context)).thenReturn(0);
assertEquals("TestCountTotal 1", 0, relationshipService.countTotal(context));
}
/** /**
* Helper method that returns a configured Relationship * Helper method that returns a configured Relationship
* @param leftItem Relationship's left item * @param leftItem Relationship's left item

View File

@@ -51,8 +51,8 @@ public class RelationshipTypeTest {
firstRelationshipType.setId(1); firstRelationshipType.setId(1);
firstRelationshipType.setLeftType(mock(EntityType.class)); firstRelationshipType.setLeftType(mock(EntityType.class));
firstRelationshipType.setRightType(mock(EntityType.class)); firstRelationshipType.setRightType(mock(EntityType.class));
firstRelationshipType.setLeftLabel("isAuthorOfPublication"); firstRelationshipType.setLeftwardType("isAuthorOfPublication");
firstRelationshipType.setRightLabel("isPublicationOfAuthor"); firstRelationshipType.setRightwardType("isPublicationOfAuthor");
firstRelationshipType.setLeftMinCardinality(0); firstRelationshipType.setLeftMinCardinality(0);
firstRelationshipType.setLeftMaxCardinality(null); firstRelationshipType.setLeftMaxCardinality(null);
firstRelationshipType.setRightMinCardinality(0); firstRelationshipType.setRightMinCardinality(0);
@@ -63,8 +63,8 @@ public class RelationshipTypeTest {
secondRelationshipType.setId(new Random().nextInt()); secondRelationshipType.setId(new Random().nextInt());
secondRelationshipType.setLeftType(mock(EntityType.class)); secondRelationshipType.setLeftType(mock(EntityType.class));
secondRelationshipType.setRightType(mock(EntityType.class)); secondRelationshipType.setRightType(mock(EntityType.class));
secondRelationshipType.setLeftLabel("isProjectOfPerson"); secondRelationshipType.setLeftwardType("isProjectOfPerson");
secondRelationshipType.setRightLabel("isPersonOfProject"); secondRelationshipType.setRightwardType("isPersonOfProject");
secondRelationshipType.setLeftMinCardinality(0); secondRelationshipType.setLeftMinCardinality(0);
secondRelationshipType.setLeftMaxCardinality(null); secondRelationshipType.setLeftMaxCardinality(null);
secondRelationshipType.setRightMinCardinality(0); secondRelationshipType.setRightMinCardinality(0);
@@ -87,11 +87,11 @@ public class RelationshipTypeTest {
@Test @Test
public void testRelationshipTypeFindByTypesAndLabels() throws Exception { public void testRelationshipTypeFindByTypesAndLabels() throws Exception {
// Mock DAO to return our firstRelationshipType // Mock DAO to return our firstRelationshipType
when(relationshipTypeDAO.findByTypesAndLabels(any(), any(), any(), any(), any())) when(relationshipTypeDAO.findbyTypesAndTypeName(any(), any(), any(), any(), any()))
.thenReturn(firstRelationshipType); .thenReturn(firstRelationshipType);
// Declare objects utilized for this test // Declare objects utilized for this test
RelationshipType found = relationshipTypeService.findbyTypesAndLabels(context, mock(EntityType.class), RelationshipType found = relationshipTypeService.findbyTypesAndTypeName(context, mock(EntityType.class),
mock(EntityType.class), mock(EntityType.class),
"mock", "mock"); "mock", "mock");
@@ -107,7 +107,7 @@ public class RelationshipTypeTest {
mockedList.add(secondRelationshipType); mockedList.add(secondRelationshipType);
// Mock DAO to return our mockedList // Mock DAO to return our mockedList
when(relationshipTypeDAO.findAll(context, RelationshipType.class)).thenReturn(mockedList); when(relationshipTypeDAO.findAll(context, RelationshipType.class, -1, -1)).thenReturn(mockedList);
// Invoke findAll() // Invoke findAll()
List<RelationshipType> foundRelationshipTypes = relationshipTypeService.findAll(context); List<RelationshipType> foundRelationshipTypes = relationshipTypeService.findAll(context);
@@ -118,16 +118,16 @@ public class RelationshipTypeTest {
} }
@Test @Test
public void testRelationshipTypeFindByLeftOrRightLabel() throws Exception { public void testRelationshipTypeFindByLeftOrRightwardType() throws Exception {
// Declare objects utilized for this test // Declare objects utilized for this test
List<RelationshipType> mockedList = new LinkedList<>(); List<RelationshipType> mockedList = new LinkedList<>();
mockedList.add(firstRelationshipType); mockedList.add(firstRelationshipType);
// Mock DAO to return our mockedList // Mock DAO to return our mockedList
when(relationshipTypeDAO.findByLeftOrRightLabel(any(), any())).thenReturn(mockedList); when(relationshipTypeDAO.findByLeftwardOrRightwardTypeName(context, "mock", -1, -1)).thenReturn(mockedList);
// Invoke findByLeftOrRightLabel() // Invoke findByLeftwardOrRightwardTypeName()
List<RelationshipType> found = relationshipTypeService.findByLeftOrRightLabel(context, "mock"); List<RelationshipType> found = relationshipTypeService.findByLeftwardOrRightwardTypeName(context, "mock");
// Assert that our expected list contains our expected RelationshipType and nothing more // Assert that our expected list contains our expected RelationshipType and nothing more
assertThat(found, notNullValue()); assertThat(found, notNullValue());
@@ -142,10 +142,11 @@ public class RelationshipTypeTest {
mockedList.add(firstRelationshipType); mockedList.add(firstRelationshipType);
// Mock DAO to return our mockedList // Mock DAO to return our mockedList
when(relationshipTypeDAO.findByEntityType(any(), any())).thenReturn(mockedList); when(relationshipTypeDAO.findByEntityType(any(), any(), any(), any())).thenReturn(mockedList);
// Invoke findByEntityType() // Invoke findByEntityType()
List<RelationshipType> found = relationshipTypeService.findByEntityType(context, mock(EntityType.class)); List<RelationshipType> found = relationshipTypeService
.findByEntityType(context, mock(EntityType.class), -1, -1);
// Assert that our expected list contains our expected RelationshipType and nothing more // Assert that our expected list contains our expected RelationshipType and nothing more
assertThat(found, notNullValue()); assertThat(found, notNullValue());
@@ -160,8 +161,8 @@ public class RelationshipTypeTest {
*/ */
private void checkRelationshipTypeValues(RelationshipType found, RelationshipType original) { private void checkRelationshipTypeValues(RelationshipType found, RelationshipType original) {
assertThat(found, notNullValue()); assertThat(found, notNullValue());
assertThat(found.getLeftLabel(), equalTo(original.getLeftLabel())); assertThat(found.getLeftwardType(), equalTo(original.getLeftwardType()));
assertThat(found.getRightLabel(), equalTo(original.getRightLabel())); assertThat(found.getRightwardType(), equalTo(original.getRightwardType()));
assertThat(found.getLeftType(), equalTo(original.getLeftType())); assertThat(found.getLeftType(), equalTo(original.getLeftType()));
assertThat(found.getRightType(), equalTo(original.getRightType())); assertThat(found.getRightType(), equalTo(original.getRightType()));
assertThat(found.getLeftMinCardinality(), equalTo(original.getLeftMinCardinality())); assertThat(found.getLeftMinCardinality(), equalTo(original.getLeftMinCardinality()));

View File

@@ -0,0 +1,186 @@
/**
* 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.dao;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.Logger;
import org.dspace.AbstractIntegrationTest;
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.WorkspaceItem;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
import org.dspace.content.service.EntityTypeService;
import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.content.service.WorkspaceItemService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Created by: Andrew Wood
* Date: 20 Sep 2019
*/
public class RelationshipDAOImplTest extends AbstractIntegrationTest {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RelationshipDAOImplTest.class);
private Relationship relationship;
private Item itemOne;
private Item itemTwo;
private Collection collection;
private Community owningCommunity;
private RelationshipType relationshipType;
private List<Relationship> relationshipsList = new ArrayList<>();
private EntityType entityTypeOne;
private EntityType entityTypeTwo;
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
protected InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService();
protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
protected RelationshipTypeService relationshipTypeService =
ContentServiceFactory.getInstance().getRelationshipTypeService();
protected RelationshipService relationshipService = ContentServiceFactory.getInstance().getRelationshipService();
protected EntityTypeService entityTypeService = ContentServiceFactory.getInstance().getEntityTypeService();
/**
* Initalize DSpace objects used for testing for each test
*/
@Before
@Override
public void init() {
super.init();
try {
// Create objects for testing
context.turnOffAuthorisationSystem();
owningCommunity = communityService.create(null, context);
collection = collectionService.create(context, owningCommunity);
WorkspaceItem workspaceItem = workspaceItemService.create(context, collection, false);
WorkspaceItem workspaceItemTwo = workspaceItemService.create(context, collection, false);
itemOne = installItemService.installItem(context, workspaceItem);
itemTwo = installItemService.installItem(context, workspaceItemTwo);
itemService.addMetadata(context, itemOne, "relationship", "type", null, Item.ANY, "Publication");
itemService.addMetadata(context, itemTwo, "relationship", "type", null, Item.ANY, "Person");
itemService.update(context, itemOne);
itemService.update(context, itemTwo);
entityTypeOne = entityTypeService.create(context, "Person");
entityTypeTwo = entityTypeService.create(context, "Publication");
relationshipType = relationshipTypeService.create(context, entityTypeTwo, entityTypeOne,
"isAuthorOfPublication", "isPublicationOfAuthor",0,10,0,10);
relationship = relationshipService.create(context, itemOne, itemTwo, relationshipType, 0, 0);
relationshipService.update(context, relationship);
relationshipsList.add(relationship);
context.restoreAuthSystemState();
} catch (Exception e) {
log.error(e);
fail(e.getMessage());
}
}
/**
* Delete all initalized DSpace objects after each test
*/
@After
@Override
public void destroy() {
try {
context.turnOffAuthorisationSystem();
relationshipService.delete(context, relationship);
relationshipTypeService.delete(context, relationshipType);
entityTypeService.delete(context, entityTypeTwo);
entityTypeService.delete(context, entityTypeOne);
itemService.delete(context, itemOne);
itemService.delete(context, itemTwo);
} catch (Exception e) {
log.error(e);
fail(e.getMessage());
}
super.destroy();
}
/**
* Test findItem should return our defined relationshipsList given our test Item itemOne.
*
* @throws Exception
*/
@Test
public void testFindByItem() throws Exception {
assertEquals("TestFindByItem 0", relationshipsList, relationshipService.findByItem(context, itemOne, -1, -1));
}
/**
* Test findLeftPlaceByLeftItem should return 0 given our test left Item itemOne.
*
* @throws Exception
*/
@Test
public void testFindLeftPlaceByLeftItem() throws Exception {
assertEquals("TestLeftPlaceByLeftItem 0", 0, relationshipService.findLeftPlaceByLeftItem(context,
itemOne));
}
/**
* Test findRightPlaceByRightItem should return 0 given our test right Item itemTwo.
*
* @throws Exception
*/
@Test
public void testFindRightPlaceByRightItem() throws Exception {
assertEquals("TestRightPlaceByRightItem 0", 0, relationshipService.findRightPlaceByRightItem(context,
itemTwo));
}
/**
* Test findByRelationshipType should return our defined relationshipsList given our test RelationshipType
* relationshipType
*
* @throws Exception
*/
@Test
public void testFindByRelationshipType() throws Exception {
assertEquals("TestByRelationshipType 0", relationshipsList, relationshipService.findByRelationshipType(context,
relationshipType));
}
/**
* Test countTotal should return our defined relationshipsList's size given our test Context
* context
*
* @throws Exception
*/
@Test
public void testCountRows() throws Exception {
assertEquals("TestByRelationshipType 0", relationshipsList.size(), relationshipService.countTotal(context));
}
}

View File

@@ -0,0 +1,161 @@
/**
* 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.dao;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.Logger;
import org.dspace.AbstractIntegrationTest;
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.WorkspaceItem;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
import org.dspace.content.service.EntityTypeService;
import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.content.service.WorkspaceItemService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class RelationshipTypeDAOImplTest extends AbstractIntegrationTest {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RelationshipTypeDAOImplTest.class);
private Relationship relationship;
private Item itemOne;
private Item itemTwo;
private Collection collection;
private Community owningCommunity;
private RelationshipType relationshipType;
private List<RelationshipType> relationshipTypeList = new ArrayList<>();
private EntityType entityTypeOne;
private EntityType entityTypeTwo;
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
protected InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService();
protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
protected RelationshipTypeService relationshipTypeService =
ContentServiceFactory.getInstance().getRelationshipTypeService();
protected RelationshipService relationshipService = ContentServiceFactory.getInstance().getRelationshipService();
protected EntityTypeService entityTypeService = ContentServiceFactory.getInstance().getEntityTypeService();
/**
* Initalize DSpace objects used for testing for each test
*/
@Before
@Override
public void init() {
super.init();
try {
context.turnOffAuthorisationSystem();
owningCommunity = communityService.create(null, context);
collection = collectionService.create(context, owningCommunity);
WorkspaceItem workspaceItem = workspaceItemService.create(context, collection, false);
WorkspaceItem workspaceItemTwo = workspaceItemService.create(context, collection, false);
itemOne = installItemService.installItem(context, workspaceItem);
itemTwo = installItemService.installItem(context, workspaceItemTwo);
itemService.addMetadata(context, itemOne, "relationship", "type", null, Item.ANY, "Publication");
itemService.addMetadata(context, itemTwo, "relationship", "type", null, Item.ANY, "Person");
itemService.update(context, itemOne);
itemService.update(context, itemTwo);
entityTypeOne = entityTypeService.create(context, "Person");
entityTypeTwo = entityTypeService.create(context, "Publication");
relationshipType = relationshipTypeService.create(context, entityTypeTwo, entityTypeOne,
"isAuthorOfPublication", "isPublicationOfAuthor",0,10,0,10);
relationship = relationshipService.create(context, itemOne, itemTwo, relationshipType, 0, 0);
relationshipService.update(context, relationship);
relationshipTypeList.add(relationshipType);
context.restoreAuthSystemState();
} catch (Exception e) {
log.error(e);
fail(e.getMessage());
}
}
/**
* Delete all initalized DSpace objects after each test
*/
@After
@Override
public void destroy() {
try {
// Cleanup newly created objects
context.turnOffAuthorisationSystem();
relationshipService.delete(context, relationship);
relationshipTypeService.delete(context, relationshipType);
entityTypeService.delete(context, entityTypeTwo);
entityTypeService.delete(context, entityTypeOne);
itemService.delete(context, itemOne);
itemService.delete(context, itemTwo);
} catch (Exception e) {
log.error(e);
fail(e.getMessage());
}
super.destroy();
}
/**
* Test findbyTypesAndLabels should return our defined RelationshipType given our test Entities entityTypeTwo and
* entityTypeOne with the affiliated labels isAuthorOfPublication and isPublicationOfAuthor
*
* @throws Exception
*/
@Test
public void testFindByTypesAndLabels() throws Exception {
assertEquals("TestFindbyTypesAndLabels 0", relationshipType, relationshipTypeService
.findbyTypesAndTypeName(context, entityTypeTwo, entityTypeOne, "isAuthorOfPublication",
"isPublicationOfAuthor"));
}
/**
* Test findByLeftOrRightLabel should return our defined relationshipTypeList given one of our affiliated labels
*
* @throws Exception
*/
@Test
public void testFindByLeftOrRightLabel() throws Exception {
assertEquals("TestFindByLeftOrRightLabel 0", relationshipTypeList, relationshipTypeService.
findByLeftwardOrRightwardTypeName(context, "isAuthorOfPublication", -1, -1));
}
/**
* Test findByEntityType should return our defined relationshipsList given one our defined EntityTypes
* entityTypeOne
*
* @throws Exception
*/
@Test
public void testFindByEntityType() throws Exception {
assertEquals("TestFindByEntityType 0", relationshipTypeList, relationshipTypeService.findByEntityType(context,
entityTypeOne));
}
}

View File

@@ -124,15 +124,15 @@ public class RelatedTest {
Entity entity = mock(Entity.class); Entity entity = mock(Entity.class);
EntityType entityType = mock(EntityType.class); EntityType entityType = mock(EntityType.class);
RelationshipType relationshipType = mock(RelationshipType.class); RelationshipType relationshipType = mock(RelationshipType.class);
related.setRelationshipTypeString("LeftLabel"); related.setRelationshipTypeString("LeftwardType");
relationshipTypeList.add(relationshipType); relationshipTypeList.add(relationshipType);
relationshipList.add(relationship); relationshipList.add(relationship);
related.setPlace(0); related.setPlace(0);
// Mock the state of objects utilized in getRelationsByLabel() to meet the success criteria of an invocation // Mock the state of objects utilized in getRelationsByLabel() to meet the success criteria of an invocation
when(item.getID()).thenReturn(UUID.randomUUID()); when(item.getID()).thenReturn(UUID.randomUUID());
when(relationshipType.getLeftLabel()).thenReturn("LeftLabel"); when(relationshipType.getLeftwardType()).thenReturn("LeftwardType");
when(relationshipType.getRightLabel()).thenReturn("RightLabel"); when(relationshipType.getRightwardType()).thenReturn("RightwardType");
when(relationshipType.getLeftType()).thenReturn(entityType); when(relationshipType.getLeftType()).thenReturn(entityType);
when(relationshipType.getRightType()).thenReturn(entityType); when(relationshipType.getRightType()).thenReturn(entityType);
when(entityService.getAllRelationshipTypes(context, entity)).thenReturn(relationshipTypeList); when(entityService.getAllRelationshipTypes(context, entity)).thenReturn(relationshipTypeList);

View File

@@ -62,15 +62,15 @@ public class VirtualMetadataPopulatorTest {
HashMap<String, VirtualMetadataConfiguration> mapExt = new HashMap<>(); HashMap<String, VirtualMetadataConfiguration> mapExt = new HashMap<>();
VirtualMetadataConfiguration virtualMetadataConfiguration = mock(VirtualMetadataConfiguration.class); VirtualMetadataConfiguration virtualMetadataConfiguration = mock(VirtualMetadataConfiguration.class);
mapExt.put("hashKey", virtualMetadataConfiguration); mapExt.put("hashKey", virtualMetadataConfiguration);
map.put("LeftLabel", mapExt); map.put("LeftwardType", mapExt);
map.put("NotRightLabel", mapExt); map.put("NotRightwardType", mapExt);
virtualMetadataPopulator.setMap(map); virtualMetadataPopulator.setMap(map);
// Mock the state of objects utilized in isUseForPlaceTrueForRelationshipType() // Mock the state of objects utilized in isUseForPlaceTrueForRelationshipType()
// to meet the success criteria of an invocation // to meet the success criteria of an invocation
when(virtualMetadataConfiguration.getUseForPlace()).thenReturn(true); when(virtualMetadataConfiguration.getUseForPlace()).thenReturn(true);
when(relationshipType.getLeftLabel()).thenReturn("LeftLabel"); when(relationshipType.getLeftwardType()).thenReturn("LeftwardType");
when(relationshipType.getRightLabel()).thenReturn("RightLabel"); when(relationshipType.getRightwardType()).thenReturn("RightwardType");
// Assert that the useForPlace for our mocked relationshipType is false // Assert that the useForPlace for our mocked relationshipType is false
assertEquals("TestGetFields 0", false, assertEquals("TestGetFields 0", false,

View File

@@ -0,0 +1,30 @@
/**
* 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.harvest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* A mock for the HarvestedCollectionService
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
public class MockHarvestedCollectionServiceImpl extends HarvestedCollectionServiceImpl {
@Override
public List<String> verifyOAIharvester(String oaiSource,
String oaiSetId, String metaPrefix, boolean testORE) {
if (metaPrefix.equals("dc")) {
return new ArrayList<>();
} else {
return Arrays.asList("(Mock error) Incorrect metadataConfigID");
}
}
}

View File

@@ -7,9 +7,13 @@
*/ */
package org.dspace.app.rest; package org.dspace.app.rest;
import static org.dspace.app.rest.utils.ContextUtil.obtainContext;
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -18,12 +22,17 @@ import javax.ws.rs.core.Response;
import org.apache.catalina.connector.ClientAbortException; import org.apache.catalina.connector.ClientAbortException;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.converter.BitstreamConverter;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.hateoas.BitstreamResource;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.MultipartFileSender; import org.dspace.app.rest.utils.MultipartFileSender;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat; import org.dspace.content.BitstreamFormat;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService; import org.dspace.content.service.BitstreamService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.disseminate.service.CitationDocumentService; import org.dspace.disseminate.service.CitationDocumentService;
@@ -31,6 +40,8 @@ import org.dspace.services.ConfigurationService;
import org.dspace.services.EventService; import org.dspace.services.EventService;
import org.dspace.usage.UsageEvent; import org.dspace.usage.UsageEvent;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@@ -54,11 +65,11 @@ import org.springframework.web.bind.annotation.RestController;
*/ */
@RestController @RestController
@RequestMapping("/api/" + BitstreamRest.CATEGORY + "/" + BitstreamRest.PLURAL_NAME @RequestMapping("/api/" + BitstreamRest.CATEGORY + "/" + BitstreamRest.PLURAL_NAME
+ "/{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}}/content") + "/{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}}")
public class BitstreamContentRestController { public class BitstreamRestController {
private static final Logger log = org.apache.logging.log4j.LogManager private static final Logger log = org.apache.logging.log4j.LogManager
.getLogger(BitstreamContentRestController.class); .getLogger(BitstreamRestController.class);
//Most file systems are configured to use block sizes of 4096 or 8192 and our buffer should be a multiple of that. //Most file systems are configured to use block sizes of 4096 or 8192 and our buffer should be a multiple of that.
private static final int BUFFER_SIZE = 4096 * 10; private static final int BUFFER_SIZE = 4096 * 10;
@@ -66,6 +77,9 @@ public class BitstreamContentRestController {
@Autowired @Autowired
private BitstreamService bitstreamService; private BitstreamService bitstreamService;
@Autowired
BitstreamFormatService bitstreamFormatService;
@Autowired @Autowired
private EventService eventService; private EventService eventService;
@@ -75,8 +89,14 @@ public class BitstreamContentRestController {
@Autowired @Autowired
private ConfigurationService configurationService; private ConfigurationService configurationService;
@Autowired
BitstreamConverter converter;
@Autowired
Utils utils;
@PreAuthorize("hasPermission(#uuid, 'BITSTREAM', 'READ')") @PreAuthorize("hasPermission(#uuid, 'BITSTREAM', 'READ')")
@RequestMapping(method = {RequestMethod.GET, RequestMethod.HEAD}) @RequestMapping( method = {RequestMethod.GET, RequestMethod.HEAD}, value = "content")
public void retrieve(@PathVariable UUID uuid, HttpServletResponse response, public void retrieve(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request) throws IOException, SQLException, AuthorizeException { HttpServletRequest request) throws IOException, SQLException, AuthorizeException {
@@ -182,4 +202,43 @@ public class BitstreamContentRestController {
return responseCode.equals(Response.Status.Family.SUCCESSFUL) return responseCode.equals(Response.Status.Family.SUCCESSFUL)
|| responseCode.equals(Response.Status.Family.REDIRECTION); || responseCode.equals(Response.Status.Family.REDIRECTION);
} }
/**
* This method will update the bitstream format of the bitstream that corresponds to the provided bitstream uuid.
*
* @param uuid The UUID of the bitstream for which to update the bitstream format
* @param request The request object
* @return The wrapped resource containing the bitstream which in turn contains the bitstream format
* @throws SQLException If something goes wrong in the database
*/
@RequestMapping(method = PUT, consumes = {"text/uri-list"}, value = "format")
@PreAuthorize("hasPermission(#uuid, 'BITSTREAM','WRITE')")
@PostAuthorize("returnObject != null")
public BitstreamResource updateBitstreamFormat(@PathVariable UUID uuid,
HttpServletRequest request) throws SQLException {
Context context = obtainContext(request);
List<BitstreamFormat> bitstreamFormats = utils.constructBitstreamFormatList(request, context);
if (bitstreamFormats.size() > 1) {
throw new DSpaceBadRequestException("Only one bitstream format is allowed");
}
BitstreamFormat bitstreamFormat = bitstreamFormats.stream().findFirst()
.orElseThrow(() -> new DSpaceBadRequestException("No valid bitstream format was provided"));
Bitstream bitstream = bitstreamService.find(context, uuid);
if (bitstream == null) {
throw new ResourceNotFoundException("Bitstream with id: " + uuid + " not found");
}
bitstream.setFormat(context, bitstreamFormat);
context.commit();
return (BitstreamResource) utils.getResourceRepository(BitstreamRest.CATEGORY, BitstreamRest.NAME)
.wrapResource(converter.fromModel(context.reloadEntity(bitstream)));
}
} }

View File

@@ -0,0 +1,125 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import java.sql.SQLException;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.converter.HarvestedCollectionConverter;
import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.HarvestedCollectionRest;
import org.dspace.app.rest.model.hateoas.HarvestedCollectionResource;
import org.dspace.app.rest.repository.HarvestedCollectionRestRepository;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.content.Collection;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Context;
import org.dspace.harvest.service.HarvestedCollectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* Rest controller that handles the harvest settings for collections
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
@RestController
@RequestMapping("/api/core/collections/" +
"{collectionUuid:[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" +
"}}/harvester")
public class CollectionHarvestSettingsController {
@Autowired
HarvestedCollectionConverter harvestedCollectionConverter;
@Autowired
CollectionService collectionService;
@Autowired
HarvestedCollectionService harvestedCollectionService;
@Autowired
private HalLinkService halLinkService;
@Autowired
HarvestedCollectionRestRepository harvestedCollectionRestRepository;
@Autowired
private Utils utils;
/**
* GET endpoint that returns the harvest settings of the given collection
* @param request The request object
* @param response The response object
* @return a HarvesterMetadataResource containing all available metadata formats
*/
@PreAuthorize("hasPermission(#collectionUuid, 'COLLECTION', 'WRITE')")
@RequestMapping(method = RequestMethod.GET)
public HarvestedCollectionResource get(@PathVariable UUID collectionUuid,
HttpServletRequest request,
HttpServletResponse response) throws SQLException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, collectionUuid);
if (collection == null) {
throw new ResourceNotFoundException("Collection with uuid: " + collectionUuid + " not found");
}
HarvestedCollectionRest harvestedCollectionRest = harvestedCollectionRestRepository.findOne(collection);
HarvestedCollectionResource resource = new HarvestedCollectionResource(harvestedCollectionRest);
halLinkService.addLinks(resource);
return resource;
}
/**
* PUT Endpoint for updating the settings of a collection.
*
* @param collectionUuid The collection whose settings should be changed
* @param response The response object
* @param request The request object
* @throws SQLException
*/
@PreAuthorize("hasPermission(#collectionUuid, 'COLLECTION', 'WRITE')")
@RequestMapping(method = RequestMethod.PUT, consumes = {"application/json"})
public HarvestedCollectionResource updateHarvestSettingsEndpoint(@PathVariable UUID collectionUuid,
HttpServletResponse response,
HttpServletRequest request) throws SQLException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, collectionUuid);
HarvestedCollectionResource harvestedCollectionResource = null;
if (collection == null) {
throw new ResourceNotFoundException("Collection with uuid: " + collectionUuid + " not found");
}
HarvestedCollectionRest harvestedCollectionRest =
harvestedCollectionRestRepository.update(context, request, collection);
// Return a harvestedCollectionResource only if a new harvestedCollection was created
if (harvestedCollectionRest != null) {
harvestedCollectionResource = new HarvestedCollectionResource(harvestedCollectionRest);
halLinkService.addLinks(harvestedCollectionResource);
}
context.commit();
return harvestedCollectionResource;
}
}

View File

@@ -0,0 +1,62 @@
/**
* 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.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.HarvesterMetadataRest;
import org.dspace.app.rest.model.hateoas.HarvesterMetadataResource;
import org.dspace.app.rest.utils.Utils;
import org.dspace.harvest.OAIHarvester;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* Rest controller that handles the harvesting metadata formats
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
@RestController
@RequestMapping("/api/config/harvestermetadata")
public class HarvesterMetadataController {
@Autowired
Utils utils;
@Autowired
private HalLinkService halLinkService;
/**
* GET endpoint that returns all available metadata formats
* @param request The request object
* @param response The response object
* @return a HarvesterMetadataResource containing all available metadata formats
*/
@RequestMapping(method = RequestMethod.GET)
public HarvesterMetadataResource get(HttpServletRequest request,
HttpServletResponse response) {
List<Map<String,String>> configs = OAIHarvester.getAvailableMetadataFormats();
HarvesterMetadataRest data = new HarvesterMetadataRest();
data.setConfigs(configs);
HarvesterMetadataResource resource = new HarvesterMetadataResource(data, utils);
halLinkService.addLinks(resource);
return resource;
}
}

View File

@@ -73,12 +73,12 @@ public class MappedCollectionRestController {
* The owning collection is not included in this list. It will transform the list of Collections to a list of * The owning collection is not included in this list. It will transform the list of Collections to a list of
* CollectionRest objects and it'll then encapsulate these into a MappedCollectionResourceWrapper object * CollectionRest objects and it'll then encapsulate these into a MappedCollectionResourceWrapper object
* *
* curl -X GET http://<dspace.restUrl>/api/core/item/{uuid}/mappedCollections * curl -X GET http://<dspace.baseUrl>/api/core/item/{uuid}/mappedCollections
* *
* Example: * Example:
* <pre> * <pre>
* {@code * {@code
* curl -X GET http://<dspace.restUrl>/api/core/items/8b632938-77c2-487c-81f0-e804f63e68e6/mappedCollections * curl -X GET http://<dspace.baseUrl>/api/core/items/8b632938-77c2-487c-81f0-e804f63e68e6/mappedCollections
* } * }
* </pre> * </pre>
* *
@@ -121,14 +121,14 @@ public class MappedCollectionRestController {
* This method will add an Item to a Collection. The Collection object is encapsulated in the request due to the * This method will add an Item to a Collection. The Collection object is encapsulated in the request due to the
* text/uri-list consumer and the Item UUID comes from the path in the URL * text/uri-list consumer and the Item UUID comes from the path in the URL
* *
* curl -X POST http://<dspace.restUrl>/api/core/item/{uuid}/mappedCollections * curl -X POST http://<dspace.baseUrl>/api/core/item/{uuid}/mappedCollections
* -H "Content-Type:text/uri-list" * -H "Content-Type:text/uri-list"
* --data $'https://{url}/rest/api/core/collections/{uuid}' * --data $'https://{url}/rest/api/core/collections/{uuid}'
* *
* Example: * Example:
* <pre> * <pre>
* {@code * {@code
* curl -X POST http://<dspace.restUrl>/api/core/item/{uuid}/mappedCollections * curl -X POST http://<dspace.baseUrl>/api/core/item/{uuid}/mappedCollections
* -H "Content-Type:text/uri-list" * -H "Content-Type:text/uri-list"
* --data $'https://{url}/rest/api/core/collections/506a7e54-8d7c-4d5b-8636-d5f6411483de' * --data $'https://{url}/rest/api/core/collections/506a7e54-8d7c-4d5b-8636-d5f6411483de'
* } * }
@@ -176,12 +176,12 @@ public class MappedCollectionRestController {
* This method will delete a Collection to Item relation. It will remove an Item with UUID given in the request * This method will delete a Collection to Item relation. It will remove an Item with UUID given in the request
* URL from the Collection with UUID given in the request URL. * URL from the Collection with UUID given in the request URL.
* *
* curl -X DELETE http://<dspace.restUrl>/api/core/item/{uuid}/mappedCollections/{collectionUuid} * curl -X DELETE http://<dspace.baseUrl>/api/core/item/{uuid}/mappedCollections/{collectionUuid}
* *
* Example: * Example:
* <pre> * <pre>
* {@code * {@code
* curl -X DELETE http://<dspace.restUrl>/api/core/item/{uuid}/mappedCollections/{collectionUuid} * curl -X DELETE http://<dspace.baseUrl>/api/core/item/{uuid}/mappedCollections/{collectionUuid}
* } * }
* </pre> * </pre>
* *

View File

@@ -67,12 +67,12 @@ public class MappedItemRestController {
* returning only items that belong to a different collection but are mapped to the given one. * returning only items that belong to a different collection but are mapped to the given one.
* These Items are then encapsulated in a MappedItemResourceWrapper and returned * These Items are then encapsulated in a MappedItemResourceWrapper and returned
* *
* curl -X GET http://<dspace.restUrl>/api/core/collections/{uuid}/mappedItems * curl -X GET http://<dspace.baseUrl>/api/core/collections/{uuid}/mappedItems
* *
* Example: * Example:
* <pre> * <pre>
* {@code * {@code
* curl -X GET http://<dspace.restUrl>/api/core/collections/8b632938-77c2-487c-81f0-e804f63e68e6/mappedItems * curl -X GET http://<dspace.baseUrl>/api/core/collections/8b632938-77c2-487c-81f0-e804f63e68e6/mappedItems
* } * }
* </pre> * </pre>
* *

View File

@@ -71,7 +71,7 @@ public class RelationshipTypeRestController {
HttpServletRequest request) throws SQLException { HttpServletRequest request) throws SQLException {
Context context = ContextUtil.obtainContext(request); Context context = ContextUtil.obtainContext(request);
EntityType entityType = entityTypeService.find(context, id); EntityType entityType = entityTypeService.find(context, id);
List<RelationshipType> list = relationshipTypeService.findByEntityType(context, entityType); List<RelationshipType> list = relationshipTypeService.findByEntityType(context, entityType, -1, -1);
List<RelationshipTypeRest> relationshipTypeRests = new LinkedList<>(); List<RelationshipTypeRest> relationshipTypeRests = new LinkedList<>();

View File

@@ -51,6 +51,7 @@ import org.dspace.app.rest.repository.LinkRestRepository;
import org.dspace.app.rest.utils.RestRepositoryUtils; import org.dspace.app.rest.utils.RestRepositoryUtils;
import org.dspace.app.rest.utils.Utils; import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.util.UUIDUtils;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -70,6 +71,7 @@ import org.springframework.hateoas.UriTemplate;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@@ -364,13 +366,13 @@ public class RestResourceController implements InitializingBean {
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG + @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG +
"/{rel}/{relid:[\\w+\\-]+}") "/{rel}/{relid}")
public ResourceSupport findRel(HttpServletRequest request, HttpServletResponse response, public ResourceSupport findRel(HttpServletRequest request, HttpServletResponse response,
@PathVariable String apiCategory, @PathVariable String apiCategory,
@PathVariable String model, @PathVariable String id, @PathVariable String rel, @PathVariable String model, @PathVariable String id, @PathVariable String rel,
@PathVariable String relid, @PathVariable String relid,
Pageable page, PagedResourcesAssembler assembler, Pageable page, PagedResourcesAssembler assembler,
@RequestParam(required = false) String projection) { @RequestParam(required = false) String projection) throws Throwable {
return findRelEntryInternal(request, response, apiCategory, model, id, rel, relid, page, assembler, projection); return findRelEntryInternal(request, response, apiCategory, model, id, rel, relid, page, assembler, projection);
} }
@@ -390,14 +392,17 @@ public class RestResourceController implements InitializingBean {
* @param request The relevant request * @param request The relevant request
* @param apiCategory The apiCategory to be used * @param apiCategory The apiCategory to be used
* @param model The model to be used * @param model The model to be used
* @param parent Optional parent identifier
* @return The relevant ResponseEntity for this request * @return The relevant ResponseEntity for this request
* @throws HttpRequestMethodNotSupportedException If something goes wrong * @throws HttpRequestMethodNotSupportedException If something goes wrong
*/ */
@RequestMapping(method = RequestMethod.POST, consumes = {"application/json", "application/hal+json"}) @RequestMapping(method = RequestMethod.POST, consumes = {"application/json", "application/hal+json"})
public ResponseEntity<ResourceSupport> post(HttpServletRequest request, @PathVariable String apiCategory, public ResponseEntity<ResourceSupport> post(HttpServletRequest request,
@PathVariable String model) @PathVariable String apiCategory,
@PathVariable String model,
@RequestParam(required = false) String parent)
throws HttpRequestMethodNotSupportedException { throws HttpRequestMethodNotSupportedException {
return postJsonInternal(request, apiCategory, model); return postJsonInternal(request, apiCategory, model, parent);
} }
/** /**
@@ -432,16 +437,24 @@ public class RestResourceController implements InitializingBean {
* @param request The relevant request * @param request The relevant request
* @param apiCategory The apiCategory to be used * @param apiCategory The apiCategory to be used
* @param model The model to be used * @param model The model to be used
* @param parent The parent object id (optional)
* @return The relevant ResponseEntity for this request * @return The relevant ResponseEntity for this request
* @throws HttpRequestMethodNotSupportedException If something goes wrong * @throws HttpRequestMethodNotSupportedException If something goes wrong
*/ */
public <ID extends Serializable> ResponseEntity<ResourceSupport> postJsonInternal(HttpServletRequest request, public <ID extends Serializable> ResponseEntity<ResourceSupport> postJsonInternal(HttpServletRequest request,
String apiCategory, String apiCategory,
String model) String model, String parent)
throws HttpRequestMethodNotSupportedException { throws HttpRequestMethodNotSupportedException {
checkModelPluralForm(apiCategory, model); checkModelPluralForm(apiCategory, model);
DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model); DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model);
RestAddressableModel modelObject = repository.createAndReturn();
RestAddressableModel modelObject;
if (parent != null) {
UUID parentUuid = UUIDUtils.fromString(parent);
modelObject = repository.createAndReturn(parentUuid);
} else {
modelObject = repository.createAndReturn();
}
if (modelObject == null) { if (modelObject == null) {
return ControllerUtils.toEmptyResponse(HttpStatus.CREATED); return ControllerUtils.toEmptyResponse(HttpStatus.CREATED);
} }
@@ -754,7 +767,7 @@ public class RestResourceController implements InitializingBean {
String id, String rel, String relid, String id, String rel, String relid,
Pageable page, Pageable page,
PagedResourcesAssembler assembler, PagedResourcesAssembler assembler,
String projection) { String projection) throws Throwable {
checkModelPluralForm(apiCategory, model); checkModelPluralForm(apiCategory, model);
DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model); DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model);
Class<RestAddressableModel> domainClass = repository.getDomainClass(); Class<RestAddressableModel> domainClass = repository.getDomainClass();
@@ -766,15 +779,26 @@ public class RestResourceController implements InitializingBean {
try { try {
Object object = linkMethod.invoke(linkRepository, request, id, relid, page, projection); Object object = linkMethod.invoke(linkRepository, request, id, relid, page, projection);
Link link = linkTo(this.getClass(), apiCategory, English.plural(model)).slash(id) Link link = linkTo(this.getClass(), apiCategory, model).slash(id).slash(rel).slash(relid).withSelfRel();
.slash(rel).withSelfRel();
List result = new ArrayList(); List result = new ArrayList();
result.add(object); result.add(object);
PageImpl<RestAddressableModel> pageResult = new PageImpl(result, page, 1); PageImpl<RestAddressableModel> pageResult = new PageImpl(result, page, 1);
Page<HALResource> halResources = pageResult.map(linkRepository::wrapResource); Page<HALResource> halResources = pageResult.map(linkRepository::wrapResource);
halResources.forEach(linkService::addLinks); halResources.forEach(linkService::addLinks);
return assembler.toResource(halResources, link); return assembler.toResource(halResources, link);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } catch (InvocationTargetException e) {
// This catch has been made to resolve the issue that caused AuthorizeDenied exceptions for the methods
// on the repository defined by the @PreAuthorize etc annotation to be absorbed by the reflection's
// InvocationTargetException and thrown as a RunTimeException when it was actually an AccessDenied
// Exception and it should be returned/shown as one
if (e.getTargetException() instanceof AccessDeniedException ||
e.getTargetException() instanceof ResourceNotFoundException) {
throw e.getTargetException();
} else {
throw new RuntimeException(e.getMessage(), e);
}
} catch (IllegalAccessException | IllegalArgumentException e) {
throw new RuntimeException(e.getMessage(), e); throw new RuntimeException(e.getMessage(), e);
} }
} }
@@ -1083,12 +1107,12 @@ public class RestResourceController implements InitializingBean {
/** /**
* Execute a PUT request for an entity with id of type UUID; * Execute a PUT request for an entity with id of type UUID;
* *
* curl -X PUT http://<dspace.restUrl>/api/{apiCategory}/{model}/{uuid} * curl -X PUT http://<dspace.baseUrl>/api/{apiCategory}/{model}/{uuid}
* *
* Example: * Example:
* <pre> * <pre>
* {@code * {@code
* curl -X PUT http://<dspace.restUrl>/api/core/collection/8b632938-77c2-487c-81f0-e804f63e68e6 * curl -X PUT http://<dspace.baseUrl>/api/core/collection/8b632938-77c2-487c-81f0-e804f63e68e6
* } * }
* </pre> * </pre>
* *

View File

@@ -0,0 +1,82 @@
/**
* 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.converter;
import java.util.List;
import java.util.Map;
import org.dspace.app.rest.model.HarvestStatusEnum;
import org.dspace.app.rest.model.HarvestTypeEnum;
import org.dspace.app.rest.model.HarvestedCollectionRest;
import org.dspace.app.rest.model.HarvesterMetadataRest;
import org.dspace.content.Collection;
import org.dspace.harvest.HarvestedCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
/**
* This is the converter from/to the HarvestedCollection in the DSpace API data model and the REST data model
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
@Component
public class HarvestedCollectionConverter implements DSpaceConverter<HarvestedCollection, HarvestedCollectionRest> {
@Autowired
private CollectionConverter collectionConverter;
@Override
public HarvestedCollectionRest fromModel(HarvestedCollection obj) {
HarvestedCollectionRest harvestedCollectionRest = new HarvestedCollectionRest();
if (obj != null) {
HarvestTypeEnum harvestTypeEnum = HarvestTypeEnum.fromInt(obj.getHarvestType());
HarvestStatusEnum harvestStatusEnum = HarvestStatusEnum.fromInt(obj.getHarvestStatus());
harvestedCollectionRest.setId(obj.getID());
harvestedCollectionRest.setCollection(collectionConverter.fromModel(obj.getCollection()));
harvestedCollectionRest.setHarvestType(harvestTypeEnum);
harvestedCollectionRest.setHarvestStatus(harvestStatusEnum);
harvestedCollectionRest.setMetadataConfigId(obj.getHarvestMetadataConfig());
harvestedCollectionRest.setOaiSetId(obj.getOaiSetId());
harvestedCollectionRest.setOaiSource(obj.getOaiSource());
harvestedCollectionRest.setHarvestMessage(obj.getHarvestMessage());
harvestedCollectionRest.setHarvestStartTime(obj.getHarvestStartTime());
harvestedCollectionRest.setLastHarvested(obj.getHarvestDate());
} else {
harvestedCollectionRest.setHarvestType(HarvestTypeEnum.NONE);
}
return harvestedCollectionRest;
}
public HarvestedCollectionRest fromModel(HarvestedCollection obj,
Collection collection,
List<Map<String,String>> metadata_configs) {
HarvestedCollectionRest harvestedCollectionRest = this.fromModel(obj);
// Add collectionRest to the empty HarvestedCollectionRest so that we can use its uuid later in the linkFactory
if (obj == null) {
harvestedCollectionRest.setCollection(collectionConverter.fromModel(collection));
}
HarvesterMetadataRest harvesterMetadataRest = new HarvesterMetadataRest();
harvesterMetadataRest.setConfigs(metadata_configs);
harvestedCollectionRest.setMetadataConfigs(harvesterMetadataRest);
return harvestedCollectionRest;
}
@Override
public HarvestedCollection toModel(HarvestedCollectionRest obj) {
throw new NotImplementedException();
}
}

View File

@@ -38,6 +38,8 @@ public class RelationshipConverter implements DSpaceConverter<Relationship, Rela
relationshipRest.setRightId(obj.getRightItem().getID()); relationshipRest.setRightId(obj.getRightItem().getID());
relationshipRest.setLeftPlace(obj.getLeftPlace()); relationshipRest.setLeftPlace(obj.getLeftPlace());
relationshipRest.setRightPlace(obj.getRightPlace()); relationshipRest.setRightPlace(obj.getRightPlace());
relationshipRest.setLeftwardValue(obj.getLeftwardValue());
relationshipRest.setRightwardValue(obj.getRightwardValue());
return relationshipRest; return relationshipRest;
} }

View File

@@ -32,8 +32,8 @@ public class RelationshipTypeConverter implements DSpaceConverter<RelationshipTy
RelationshipTypeRest relationshipTypeRest = new RelationshipTypeRest(); RelationshipTypeRest relationshipTypeRest = new RelationshipTypeRest();
relationshipTypeRest.setId(obj.getID()); relationshipTypeRest.setId(obj.getID());
relationshipTypeRest.setLeftLabel(obj.getLeftLabel()); relationshipTypeRest.setLeftwardType(obj.getLeftwardType());
relationshipTypeRest.setRightLabel(obj.getRightLabel()); relationshipTypeRest.setRightwardType(obj.getRightwardType());
relationshipTypeRest.setLeftMinCardinality(obj.getLeftMinCardinality()); relationshipTypeRest.setLeftMinCardinality(obj.getLeftMinCardinality());
relationshipTypeRest.setLeftMaxCardinality(obj.getLeftMaxCardinality()); relationshipTypeRest.setLeftMaxCardinality(obj.getLeftMaxCardinality());
relationshipTypeRest.setRightMinCardinality(obj.getRightMinCardinality()); relationshipTypeRest.setRightMinCardinality(obj.getRightMinCardinality());

View File

@@ -13,7 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* This class converts the restUrl and constructs a RootRest instance to return * This class read the core configuration properties and constructs a RootRest instance to return
*/ */
@Component @Component
public class RootConverter { public class RootConverter {
@@ -25,7 +25,7 @@ public class RootConverter {
RootRest rootRest = new RootRest(); RootRest rootRest = new RootRest();
rootRest.setDspaceName(configurationService.getProperty("dspace.name")); rootRest.setDspaceName(configurationService.getProperty("dspace.name"));
rootRest.setDspaceURL(configurationService.getProperty("dspace.url")); rootRest.setDspaceURL(configurationService.getProperty("dspace.url"));
rootRest.setDspaceRest(configurationService.getProperty("dspace.restUrl")); rootRest.setDspaceRest(configurationService.getProperty("dspace.baseUrl"));
return rootRest; return rootRest;
} }
} }

View File

@@ -44,9 +44,13 @@ public class AuthorityEntryHalLinkFactory extends HalLinkFactory<AuthorityEntryR
entry.getOtherInformation().get(AuthorityUtils.RESERVED_KEYMAP_PARENT), null, null, entry.getOtherInformation().get(AuthorityUtils.RESERVED_KEYMAP_PARENT), null, null,
null)).toUriComponentsBuilder(); null)).toUriComponentsBuilder();
list.add(buildLink(uriComponentsBuilder.build().toString(), AuthorityUtils.RESERVED_KEYMAP_PARENT)); list.add(buildLink(AuthorityUtils.RESERVED_KEYMAP_PARENT, uriComponentsBuilder.build().toString()));
} }
} }
String selfLinkString = linkTo(
getMethodOn().findOne(entry.getCategory(), English.plural(entry.getType()), entry.getAuthorityName(), null))
.toUriComponentsBuilder().build().toString() + "/entryValues/" + entry.getId();
list.add(buildLink(Link.REL_SELF, selfLinkString));
} }
protected Class<RestResourceController> getControllerClass() { protected Class<RestResourceController> getControllerClass() {

View File

@@ -0,0 +1,44 @@
/**
* 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.harvest;
import java.util.LinkedList;
import java.util.UUID;
import org.dspace.app.rest.model.HarvestedCollectionRest;
import org.dspace.app.rest.model.hateoas.HarvestedCollectionResource;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link;
import org.springframework.stereotype.Component;
/**
* This class adds links to {@link org.dspace.app.rest.model.hateoas.HarvestedCollectionResource}s
* This builds a link to the collection harvest link
*/
@Component
public class HarvestedCollectionHalLinkFactory
extends HarvestedCollectionRestHalLinkFactory<HarvestedCollectionResource> {
protected void addLinks(HarvestedCollectionResource halResource, Pageable page, LinkedList<Link> list)
throws Exception {
HarvestedCollectionRest data = halResource.getContent();
if (data != null) {
list.add(
buildLink(
Link.REL_SELF,
getMethodOn().get(UUID.fromString(data.getCollectionRest().getUuid()), null, null)
)
);
}
}
protected Class<HarvestedCollectionResource> getResourceClass() {
return HarvestedCollectionResource.class;
}
}

View File

@@ -0,0 +1,20 @@
/**
* 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.harvest;
import org.dspace.app.rest.CollectionHarvestSettingsController;
import org.dspace.app.rest.link.HalLinkFactory;
public abstract class HarvestedCollectionRestHalLinkFactory<T>
extends HalLinkFactory<T, CollectionHarvestSettingsController> {
@Override
protected Class<CollectionHarvestSettingsController> getControllerClass() {
return CollectionHarvestSettingsController.class;
}
}

View File

@@ -24,7 +24,7 @@ public class StatisticsSupportHalLinkFactory
list.add(buildLink(Link.REL_SELF, getMethodOn().getStatisticsSupport())); list.add(buildLink(Link.REL_SELF, getMethodOn().getStatisticsSupport()));
list.add(buildLink("viewevents", getMethodOn().getViewEvents())); list.add(buildLink("viewevents", getMethodOn().getViewEvents()));
list.add(buildLink("searchevents", getMethodOn().getViewEvents())); list.add(buildLink("searchevents", getMethodOn().getSearchEvents()));
} }
protected Class<StatisticsRestController> getControllerClass() { protected Class<StatisticsRestController> getControllerClass() {

View File

@@ -26,6 +26,7 @@ public class CollectionRest extends DSpaceObjectRest {
public static final String PLURAL_NAME = "collections"; public static final String PLURAL_NAME = "collections";
public static final String CATEGORY = RestAddressableModel.CORE; public static final String CATEGORY = RestAddressableModel.CORE;
public static final String LICENSE = "license"; public static final String LICENSE = "license";
public static final String HARVEST = "harvester";
public static final String DEFAULT_ACCESS_CONDITIONS = "defaultAccessConditions"; public static final String DEFAULT_ACCESS_CONDITIONS = "defaultAccessConditions";
@JsonIgnore @JsonIgnore
private BitstreamRest logo; private BitstreamRest logo;

View File

@@ -0,0 +1,47 @@
/**
* 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;
/**
* An enum containing all the possible harvest statuses
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
public enum HarvestStatusEnum {
READY(0),
BUSY(1),
QUEUED(2),
OAI_ERROR(3),
UNKNOWN_ERROR(-1);
private int harvestStatus;
HarvestStatusEnum(int harvestStatus) {
this.harvestStatus = harvestStatus;
}
public int getValue() {
return harvestStatus;
}
public static HarvestStatusEnum fromInt(Integer harvestStatus) {
if (harvestStatus == null) {
return null;
}
switch (harvestStatus) {
case -1: return HarvestStatusEnum.UNKNOWN_ERROR;
case 0: return HarvestStatusEnum.READY;
case 1: return HarvestStatusEnum.BUSY;
case 2: return HarvestStatusEnum.QUEUED;
case 3: return HarvestStatusEnum.OAI_ERROR;
default: throw new IllegalArgumentException("No corresponding enum value for integer");
}
}
}

View File

@@ -0,0 +1,49 @@
/**
* 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;
/**
* An enum containing all the possible harvest types
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
public enum HarvestTypeEnum {
NONE(0),
METADATA_ONLY(1),
METADATA_AND_REF(2),
METADATA_AND_BITSTREAMS(3);
private int harvestType;
HarvestTypeEnum(int harvestType) {
this.harvestType = harvestType;
}
public int getValue() {
return harvestType;
}
/**
* Creates an enum from the given integer
* @param harvestType The harvest type
* @return a harvestTypeEnum
*/
public static HarvestTypeEnum fromInt(Integer harvestType) {
if (harvestType == null) {
return HarvestTypeEnum.NONE;
}
switch (harvestType) {
case 0: return HarvestTypeEnum.NONE;
case 1: return HarvestTypeEnum.METADATA_ONLY;
case 2: return HarvestTypeEnum.METADATA_AND_REF;
case 3: return HarvestTypeEnum.METADATA_AND_BITSTREAMS;
default: throw new IllegalArgumentException("No corresponding enum value for integer");
}
}
}

View File

@@ -0,0 +1,170 @@
/**
* 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.Date;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* The HarvestCollection REST Resource
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
public class HarvestedCollectionRest extends BaseObjectRest<Integer> {
public static final String NAME = "collections";
public static final String CATEGORY = "core";
@JsonProperty("harvest_type")
private HarvestTypeEnum harvestType;
@JsonProperty("oai_source")
private String oaiSource;
@JsonProperty("oai_set_id")
private String oaiSetId;
@JsonProperty("harvest_message")
private String harvestMessage;
@JsonProperty("metadata_config_id")
private String metadataConfigId;
@JsonProperty("harvest_status")
private HarvestStatusEnum harvestStatus;
@JsonProperty("harvest_start_time")
private Date harvestStartTime;
@JsonProperty("last_harvested")
private Date lastHarvested;
private HarvesterMetadataRest metadata_configs;
private CollectionRest collectionRest;
@JsonIgnore
@Override
public Integer getId() {
return id;
}
public String getCategory() {
return CATEGORY;
}
public Class getController() {
return HarvestedCollectionRest.class;
}
@JsonIgnore
public String getType() {
return NAME;
}
@JsonIgnore
public CollectionRest getCollectionRest() {
return this.collectionRest;
}
public void setCollection(CollectionRest collectionRest) {
this.collectionRest = collectionRest;
}
@JsonIgnore
public int getHarvestType() {
return harvestType.ordinal();
}
@JsonGetter("harvest_type")
public String getHarvestTypeAsString() {
return harvestType.name();
}
public void setHarvestType(HarvestTypeEnum harvestType) {
this.harvestType = harvestType;
}
public String getOaiSource() {
return oaiSource;
}
public void setOaiSource(String oaiSource) {
this.oaiSource = oaiSource;
}
public String getOaiSetId() {
return oaiSetId;
}
public void setOaiSetId(String oaiSetId) {
this.oaiSetId = oaiSetId;
}
public String getMetadataConfigId() {
return metadataConfigId;
}
public void setMetadataConfigId(String metadataConfigId) {
this.metadataConfigId = metadataConfigId;
}
public String getHarvestMessage() {
return harvestMessage;
}
public void setHarvestMessage(String harvestMessage) {
this.harvestMessage = harvestMessage;
}
@JsonIgnore
public HarvestStatusEnum getHarvestStatus() {
return harvestStatus;
}
@JsonGetter("harvest_status")
public String getHarvestStatusAsString() {
return harvestStatus == null ? null : harvestStatus.name();
}
public void setHarvestStatus(HarvestStatusEnum harvestStatus) {
this.harvestStatus = harvestStatus;
}
public Date getHarvestStartTime() {
return harvestStartTime;
}
public void setHarvestStartTime(Date harvestStartTime) {
this.harvestStartTime = harvestStartTime;
}
public Date getLastHarvested() {
return lastHarvested;
}
public void setLastHarvested(Date lastHarvested) {
this.lastHarvested = lastHarvested;
}
@LinkRest(linkClass = HarvesterMetadataRest.class, name = "harvestermetadata", optional = true)
@JsonIgnore
public HarvesterMetadataRest getMetadataConfigs() {
return metadata_configs;
}
public void setMetadataConfigs(HarvesterMetadataRest metadata_configs) {
this.metadata_configs = metadata_configs;
}
}

View File

@@ -0,0 +1,58 @@
/**
* 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.io.Serializable;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.dspace.app.rest.HarvesterMetadataController;
/**
* The rest resource used for harvester metadata
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
public class HarvesterMetadataRest extends BaseObjectRest {
public static final String CATEGORY = "config";
public static final String NAME = "harvesterMetadata";
private List<Map<String,String>> configs;
@Override
@JsonIgnore
public Serializable getId() {
return id;
}
@JsonIgnore
public String getCategory() {
return CATEGORY;
}
@JsonIgnore
public String getType() {
return NAME;
}
public Class getController() {
return HarvesterMetadataController.class;
}
public List<Map<String,String>> getConfigs() {
return configs;
}
public void setConfigs(List<Map<String,String>> configs) {
this.configs = configs;
}
}

View File

@@ -30,6 +30,8 @@ public class RelationshipRest extends BaseObjectRest<Integer> {
private RelationshipTypeRest relationshipType; private RelationshipTypeRest relationshipType;
private int leftPlace; private int leftPlace;
private int rightPlace; private int rightPlace;
private String leftwardValue;
private String rightwardValue;
public String getType() { public String getType() {
return NAME; return NAME;
@@ -92,4 +94,20 @@ public class RelationshipRest extends BaseObjectRest<Integer> {
public void setRelationshipTypeId(int relationshipTypeId) { public void setRelationshipTypeId(int relationshipTypeId) {
this.relationshipTypeId = relationshipTypeId; this.relationshipTypeId = relationshipTypeId;
} }
public String getRightwardValue() {
return rightwardValue;
}
public void setRightwardValue(String rightwardValue) {
this.rightwardValue = rightwardValue;
}
public String getLeftwardValue() {
return leftwardValue;
}
public void setLeftwardValue(String leftwardValue) {
this.leftwardValue = leftwardValue;
}
} }

View File

@@ -20,8 +20,8 @@ public class RelationshipTypeRest extends BaseObjectRest<Integer> {
public static final String NAME = "relationshiptype"; public static final String NAME = "relationshiptype";
public static final String CATEGORY = "core"; public static final String CATEGORY = "core";
private String leftLabel; private String leftwardType;
private String rightLabel; private String rightwardType;
private Integer leftMinCardinality; private Integer leftMinCardinality;
private Integer leftMaxCardinality; private Integer leftMaxCardinality;
private Integer rightMinCardinality; private Integer rightMinCardinality;
@@ -41,20 +41,20 @@ public class RelationshipTypeRest extends BaseObjectRest<Integer> {
return RestResourceController.class; return RestResourceController.class;
} }
public String getLeftLabel() { public String getLeftwardType() {
return leftLabel; return leftwardType;
} }
public void setLeftLabel(String leftLabel) { public void setLeftwardType(String leftwardType) {
this.leftLabel = leftLabel; this.leftwardType = leftwardType;
} }
public String getRightLabel() { public String getRightwardType() {
return rightLabel; return rightwardType;
} }
public void setRightLabel(String rightLabel) { public void setRightwardType(String rightwardType) {
this.rightLabel = rightLabel; this.rightwardType = rightwardType;
} }
public Integer getLeftMinCardinality() { public Integer getLeftMinCardinality() {

View File

@@ -22,6 +22,7 @@ public class CollectionResource extends DSpaceResource<CollectionRest> {
public CollectionResource(CollectionRest collection, Utils utils, String... rels) { public CollectionResource(CollectionRest collection, Utils utils, String... rels) {
super(collection, utils, rels); super(collection, utils, rels);
add(utils.linkToSubResource(collection, CollectionRest.LICENSE)); add(utils.linkToSubResource(collection, CollectionRest.LICENSE));
add(utils.linkToSubResource(collection, CollectionRest.HARVEST));
add(utils.linkToSubResource(collection, "mappedItems")); add(utils.linkToSubResource(collection, "mappedItems"));
} }
} }

View File

@@ -0,0 +1,39 @@
/**
* 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 org.dspace.app.rest.model.HarvestedCollectionRest;
import org.dspace.app.rest.model.HarvesterMetadataRest;
import org.dspace.app.rest.utils.Utils;
import org.springframework.beans.factory.annotation.Autowired;
/**
* HarvestedCollection Rest HAL Resource. The HAL Resource wraps the REST Resource
* adding support for the links and embedded resources
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
public class HarvestedCollectionResource extends HALResource<HarvestedCollectionRest> {
@Autowired
private Utils utils;
public HarvestedCollectionResource(HarvestedCollectionRest data) {
super(data);
embedResource("harvestermetadata", data.getMetadataConfigs());
}
private void embedResource(String relationship, HarvesterMetadataRest harvesterMetadataRest) {
if (harvesterMetadataRest != null) {
HarvesterMetadataResource harvesterMetadataResource =
new HarvesterMetadataResource(harvesterMetadataRest, utils);
embedResource(relationship, harvesterMetadataResource);
}
}
}

View File

@@ -0,0 +1,25 @@
/**
* 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 org.dspace.app.rest.model.HarvesterMetadataRest;
import org.dspace.app.rest.utils.Utils;
/**
* HarvesterMetadata Rest HAL Resource. The HAL Resource wraps the REST Resource
* adding support for the links and embedded resources
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
public class HarvesterMetadataResource extends DSpaceResource<HarvesterMetadataRest> {
public HarvesterMetadataResource(HarvesterMetadataRest data, Utils utils, String... rels) {
super(data, utils, rels);
}
}

View File

@@ -20,6 +20,7 @@ import org.dspace.content.authority.service.ChoiceAuthorityService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -49,6 +50,9 @@ public class AuthorityEntryValueLinkRepository extends AbstractDSpaceRestReposit
Context context = obtainContext(); Context context = obtainContext();
ChoiceAuthority choiceAuthority = cas.getChoiceAuthorityByAuthorityName(name); ChoiceAuthority choiceAuthority = cas.getChoiceAuthorityByAuthorityName(name);
Choice choice = choiceAuthority.getChoice(null, relId, context.getCurrentLocale().toString()); Choice choice = choiceAuthority.getChoice(null, relId, context.getCurrentLocale().toString());
if (choice == null) {
throw new ResourceNotFoundException("The authority was not found");
}
return authorityUtils.convertEntry(choice, name); return authorityUtils.convertEntry(choice, name);
} }

View File

@@ -41,7 +41,6 @@ import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService; import org.dspace.content.service.CommunityService;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.util.UUIDUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
@@ -178,8 +177,19 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
} }
@Override @Override
@PreAuthorize("hasAuthority('ADMIN')")
protected CollectionRest createAndReturn(Context context) throws AuthorizeException { protected CollectionRest createAndReturn(Context context) throws AuthorizeException {
throw new DSpaceBadRequestException("Cannot create a Collection without providing a parent Community.");
}
@Override
@PreAuthorize("hasPermission(#id, 'COMMUNITY', 'ADD')")
protected CollectionRest createAndReturn(Context context, UUID id) throws AuthorizeException {
if (id == null) {
throw new DSpaceBadRequestException("Parent Community UUID is null. " +
"Cannot create a Collection without providing a parent Community");
}
HttpServletRequest req = getRequestService().getCurrentRequest().getHttpServletRequest(); HttpServletRequest req = getRequestService().getCurrentRequest().getHttpServletRequest();
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
CollectionRest collectionRest; CollectionRest collectionRest;
@@ -187,38 +197,21 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
ServletInputStream input = req.getInputStream(); ServletInputStream input = req.getInputStream();
collectionRest = mapper.readValue(input, CollectionRest.class); collectionRest = mapper.readValue(input, CollectionRest.class);
} catch (IOException e1) { } catch (IOException e1) {
throw new UnprocessableEntityException("Error parsing request body: " + e1.toString()); throw new UnprocessableEntityException("Error parsing request body.", e1);
} }
Collection collection; Collection collection;
String parentCommunityString = req.getParameter("parent");
try { try {
Community parent = null; Community parent = communityService.find(context, id);
if (StringUtils.isNotBlank(parentCommunityString)) { if (parent == null) {
throw new UnprocessableEntityException("Parent community for id: "
UUID parentCommunityUuid = UUIDUtils.fromString(parentCommunityString); + id + " not found");
if (parentCommunityUuid == null) {
throw new DSpaceBadRequestException("The given parent was invalid: "
+ parentCommunityString);
}
parent = communityService.find(context, parentCommunityUuid);
if (parent == null) {
throw new UnprocessableEntityException("Parent community for id: "
+ parentCommunityUuid + " not found");
}
} else {
throw new DSpaceBadRequestException("The parent parameter cannot be left empty," +
"collections require a parent community.");
} }
collection = cs.create(context, parent); collection = cs.create(context, parent);
cs.update(context, collection); cs.update(context, collection);
metadataConverter.setMetadata(context, collection, collectionRest.getMetadata()); metadataConverter.setMetadata(context, collection, collectionRest.getMetadata());
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException("Unable to create new Collection under parent Community " + throw new RuntimeException("Unable to create new Collection under parent Community " + id, e);
parentCommunityString, e);
} }
return converter.convert(collection); return converter.convert(collection);
} }

View File

@@ -17,7 +17,6 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.Parameter; import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.SearchRestMethod;
@@ -37,7 +36,6 @@ import org.dspace.content.Community;
import org.dspace.content.service.BitstreamService; import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.CommunityService; import org.dspace.content.service.CommunityService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.util.UUIDUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
@@ -93,25 +91,45 @@ public class CommunityRestRepository extends DSpaceObjectRestRepository<Communit
} }
Community community; Community community;
try { try {
Community parent = null; // top-level community
String parentCommunityString = req.getParameter("parent"); community = cs.create(null, context);
if (StringUtils.isNotBlank(parentCommunityString)) { cs.update(context, community);
metadataConverter.setMetadata(context, community, communityRest.getMetadata());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
UUID parentCommunityUuid = UUIDUtils.fromString(parentCommunityString); return dsoConverter.convert(community);
if (parentCommunityUuid == null) { }
throw new DSpaceBadRequestException("The given parent parameter was invalid: "
+ parentCommunityString);
}
parent = cs.find(context, parentCommunityUuid); @Override
if (parent == null) { @PreAuthorize("hasPermission(#id, 'COMMUNITY', 'ADD')")
throw new UnprocessableEntityException("Parent community for id: " protected CommunityRest createAndReturn(Context context, UUID id) throws AuthorizeException {
+ parentCommunityUuid + " not found");
} if (id == null) {
throw new DSpaceBadRequestException("Parent Community UUID is null. " +
"Cannot create a SubCommunity without providing a parent Community.");
}
HttpServletRequest req = getRequestService().getCurrentRequest().getHttpServletRequest();
ObjectMapper mapper = new ObjectMapper();
CommunityRest communityRest;
try {
ServletInputStream input = req.getInputStream();
communityRest = mapper.readValue(input, CommunityRest.class);
} catch (IOException e1) {
throw new UnprocessableEntityException("Error parsing request body.", e1);
}
Community community;
try {
Community parent = cs.find(context, id);
if (parent == null) {
throw new UnprocessableEntityException("Parent community for id: "
+ id + " not found");
} }
// sub-community
community = cs.create(parent, context); community = cs.create(parent, context);
cs.update(context, community); cs.update(context, community);
metadataConverter.setMetadata(context, community, communityRest.getMetadata()); metadataConverter.setMetadata(context, community, communityRest.getMetadata());

View File

@@ -12,6 +12,7 @@ import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@@ -233,7 +234,7 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
} }
/** /**
* Method to implement to support scroll of entity instances from the collection resource endpoin * Method to implement to support scroll of entity instances from the collection resource endpoint
* *
* @param context * @param context
* the dspace context * the dspace context
@@ -259,6 +260,46 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
*/ */
public abstract DSpaceResource<T> wrapResource(T model, String... rels); public abstract DSpaceResource<T> wrapResource(T model, String... rels);
/**
* Create and return a new instance. Data are usually retrieved from the thread bound http request
*
* @return the created REST object
*/
public T createAndReturn() {
Context context = null;
try {
context = obtainContext();
T entity = thisRepository.createAndReturn(context);
context.commit();
return entity;
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (SQLException ex) {
throw new RuntimeException(ex.getMessage(), ex);
}
}
/**
* Create and return a new instance after adding to the parent. Data are usually retrieved from
* the thread bound http request.
*
* @param uuid the id of the parent object
* @return the created REST object
*/
public T createAndReturn(UUID uuid) {
Context context = null;
try {
context = obtainContext();
T entity = thisRepository.createAndReturn(context, uuid);
context.commit();
return entity;
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (SQLException ex) {
throw new RuntimeException(ex.getMessage(), ex);
}
}
/** /**
* Create and return a new instance. Data is recovered from the thread bound HTTP request and the list * Create and return a new instance. Data is recovered from the thread bound HTTP request and the list
* of DSpaceObjects provided in the uri-list body * of DSpaceObjects provided in the uri-list body
@@ -281,22 +322,22 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
} }
/** /**
* Create and return a new instance. Data are usually retrieved from the thread bound http request * Method to implement to support the creation of a new instance. Usually require to retrieve the http request from
* the thread bound attribute
* *
* @param context
* the dspace context
* @param uuid
* The uuid of the parent object retrieved from the query param.
* @return the created REST object * @return the created REST object
* @throws AuthorizeException
* @throws SQLException
* @throws RepositoryMethodNotImplementedException
* returned by the default implementation when the operation is not supported for the entity
*/ */
public T createAndReturn() { protected T createAndReturn(Context context, UUID uuid)
Context context = null; throws AuthorizeException, SQLException, RepositoryMethodNotImplementedException {
try { throw new RepositoryMethodNotImplementedException("No implementation found; Method not allowed!", "");
context = obtainContext();
T entity = thisRepository.createAndReturn(context);
context.commit();
return entity;
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (SQLException ex) {
throw new RuntimeException(ex.getMessage(), ex);
}
} }
/** /**

View File

@@ -0,0 +1,190 @@
/**
* 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.repository;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.rest.converter.HarvestedCollectionConverter;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.HarvestTypeEnum;
import org.dspace.app.rest.model.HarvestedCollectionRest;
import org.dspace.content.Collection;
import org.dspace.core.Context;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.harvest.OAIHarvester;
import org.dspace.harvest.service.HarvestedCollectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* This is the repository responsible for managing the HarvestedCollection Rest object
*
* @author Jelle Pelgrims (jelle.pelgrims at atmire.com)
*/
@Component(HarvestedCollectionRest.CATEGORY + "." + HarvestedCollectionRest.NAME)
public class HarvestedCollectionRestRepository extends AbstractDSpaceRestRepository {
@Autowired
HarvestedCollectionService harvestedCollectionService;
@Autowired
HarvestedCollectionConverter harvestedCollectionConverter;
public HarvestedCollectionRest findOne(Collection collection) throws SQLException {
Context context = obtainContext();
if (collection == null) {
return null;
}
HarvestedCollection harvestedCollection = harvestedCollectionService.find(context, collection);
List<Map<String,String>> configs = OAIHarvester.getAvailableMetadataFormats();
return harvestedCollectionConverter.fromModel(harvestedCollection, collection, configs);
}
/**
* Function to update the harvesting settings of a collection
* @param context The context object
* @param request The incoming put request
* @param collection The collection whose settings should be changed
* @return a harvestedCollection if a new harvestedCollection is created, otherwise null
* @throws SQLException
*/
public HarvestedCollectionRest update(Context context,
HttpServletRequest request,
Collection collection) throws SQLException {
HarvestedCollectionRest harvestedCollectionRest = parseHarvestedCollectionRest(context, request, collection);
HarvestedCollection harvestedCollection = harvestedCollectionService.find(context, collection);
// Delete harvestedCollectionService object if harvest type is not set
if (harvestedCollectionRest.getHarvestType() == HarvestTypeEnum.NONE.getValue()
&& harvestedCollection != null) {
harvestedCollectionService.delete(context, harvestedCollection);
return harvestedCollectionConverter.fromModel(null);
} else if (harvestedCollectionRest.getHarvestType() != HarvestTypeEnum.NONE.getValue()) {
List<String> errors = testHarvestSettings(harvestedCollectionRest);
if (errors.size() == 0) {
if (harvestedCollection == null) {
harvestedCollection = harvestedCollectionService.create(context, collection);
}
updateCollectionHarvestSettings(context, harvestedCollection, harvestedCollectionRest);
harvestedCollection = harvestedCollectionService.find(context, collection);
List<Map<String,String>> configs = OAIHarvester.getAvailableMetadataFormats();
return harvestedCollectionConverter.fromModel(harvestedCollection, collection, configs);
} else {
throw new UnprocessableEntityException(
"Incorrect harvest settings in request. The following errors were found: " + errors.toString()
);
}
}
return null;
}
/**
* Function to parse a harvestedCollectionRest from an incoming put request
* @param context The context object
* @param request The incoming put request
* @param collection The collection to which the harvestedCollection belongs
* @return The harvestedCollectionRest object contained inn the request
*/
private HarvestedCollectionRest parseHarvestedCollectionRest(Context context,
HttpServletRequest request,
Collection collection) throws SQLException {
ObjectMapper mapper = new ObjectMapper();
HarvestedCollectionRest harvestedCollectionRest;
try {
ServletInputStream input = request.getInputStream();
harvestedCollectionRest = mapper.readValue(input, HarvestedCollectionRest.class);
} catch (IOException e) {
throw new UnprocessableEntityException("Error parsing request body: " + e.toString(), e);
}
return harvestedCollectionRest;
}
/**
* Function to update the harvest settings of a collection
* @param context The context object
* @param harvestedCollection The harvestedCollection whose settings should be updated
* @param harvestedCollectionRest An object containing the new harvest settings
* @throws SQLException
*/
private void updateCollectionHarvestSettings(Context context, HarvestedCollection harvestedCollection,
HarvestedCollectionRest harvestedCollectionRest) throws SQLException {
int harvestType = harvestedCollectionRest.getHarvestType();
String oaiSource = harvestedCollectionRest.getOaiSource();
String oaiSetId = harvestedCollectionRest.getOaiSetId();
String metadataConfigId = harvestedCollectionRest.getMetadataConfigId();
harvestedCollection.setHarvestType(harvestType);
harvestedCollection.setOaiSource(oaiSource);
harvestedCollection.setOaiSetId(oaiSetId);
harvestedCollection.setHarvestMetadataConfig(metadataConfigId);
harvestedCollectionService.update(context, harvestedCollection);
}
/**
* Function used to verify that the harvest settings work
* @param collection The collection to which the harvest settings should be aplied
* @param harvestedCollectionRest A object containg the harvest settings to be tested
* @return
*/
private List<String> testHarvestSettings(HarvestedCollectionRest harvestedCollectionRest) {
int harvestType = harvestedCollectionRest.getHarvestType();
String metadataConfigId = harvestedCollectionRest.getMetadataConfigId();
List<String> errors = new ArrayList<>();
// See if metadata config identifier appears in available metadata formats
List<Map<String,String>> metadataFormats = OAIHarvester.getAvailableMetadataFormats();
boolean inAvailableMetadataFormats = metadataFormats.stream()
.filter(x -> x.get("id").equals(metadataConfigId))
.count() >= 1;
if (inAvailableMetadataFormats) {
boolean testORE = Arrays.asList(
HarvestTypeEnum.METADATA_AND_REF.getValue(),
HarvestTypeEnum.METADATA_AND_BITSTREAMS.getValue()
).contains(harvestType);
// Actually verify the harvest settings
List<String> verificationErrors = harvestedCollectionService.verifyOAIharvester(
harvestedCollectionRest.getOaiSource(),
harvestedCollectionRest.getOaiSetId(),
metadataConfigId,
testORE
);
errors = verificationErrors;
} else {
errors.add(
"The metadata format with identifier '" + metadataConfigId + "' is not an available metadata format."
);
}
return errors;
}
}

View File

@@ -7,12 +7,16 @@
*/ */
package org.dspace.app.rest.repository; package org.dspace.app.rest.repository;
import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.rest.Parameter; import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.SearchRestMethod;
@@ -37,6 +41,7 @@ import org.dspace.core.Context;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
@@ -79,13 +84,17 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
} }
public Page<RelationshipRest> findAll(Context context, Pageable pageable) { public Page<RelationshipRest> findAll(Context context, Pageable pageable) {
List<Relationship> relationships = null; int total = 0;
List<Relationship> relationships = new ArrayList<>();
try { try {
relationships = relationshipService.findAll(context); total = relationshipService.countTotal(context);
relationships = relationshipService.findAll(context,
pageable.getPageSize(), pageable.getOffset());
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e); throw new RuntimeException(e.getMessage(), e);
} }
Page<RelationshipRest> page = utils.getPage(relationships, pageable).map(relationshipConverter); Page<RelationshipRest> page = new PageImpl<Relationship>(relationships,
pageable, total).map(relationshipConverter);
return page; return page;
} }
@@ -109,11 +118,14 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
RelationshipType relationshipType = relationshipTypeService RelationshipType relationshipType = relationshipTypeService
.find(context, Integer.parseInt(req.getParameter("relationshipType"))); .find(context, Integer.parseInt(req.getParameter("relationshipType")));
String leftwardValue = req.getParameter("leftwardValue");
String rightwardValue = req.getParameter("rightwardValue");
EPerson ePerson = context.getCurrentUser(); EPerson ePerson = context.getCurrentUser();
if (authorizeService.authorizeActionBoolean(context, leftItem, Constants.WRITE) || if (authorizeService.authorizeActionBoolean(context, leftItem, Constants.WRITE) ||
authorizeService.authorizeActionBoolean(context, rightItem, Constants.WRITE)) { authorizeService.authorizeActionBoolean(context, rightItem, Constants.WRITE)) {
Relationship relationship = relationshipService.create(context, leftItem, rightItem, Relationship relationship = relationshipService.create(context, leftItem, rightItem,
relationshipType, 0, 0); relationshipType, 0, 0, leftwardValue, rightwardValue);
// The above if check deals with the case that a Relationship can be created if the user has write // The above if check deals with the case that a Relationship can be created if the user has write
// rights on one of the two items. The following updateItem calls can however call the // rights on one of the two items. The following updateItem calls can however call the
// ItemService.update() functions which would fail if the user doesn't have permission on both items. // ItemService.update() functions which would fail if the user doesn't have permission on both items.
@@ -198,6 +210,66 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
} }
/**
* Method to replace the metadata of a relationship (the left/right places and the leftward/rightward labels)
* @param context the dspace context
* @param request
* @param apiCategory the API category e.g. "api"
* @param model the DSpace model e.g. "metadatafield"
* @param id the ID of the target REST object
* @param jsonNode the part of the request body representing the updated rest object
* @return
* @throws RepositoryMethodNotImplementedException
* @throws SQLException
* @throws AuthorizeException
*/
@Override
protected RelationshipRest put(Context context, HttpServletRequest request, String apiCategory, String model,
Integer id, JsonNode jsonNode)
throws RepositoryMethodNotImplementedException, SQLException, AuthorizeException {
Relationship relationship;
try {
relationship = relationshipService.find(context, id);
} catch (SQLException e) {
throw new ResourceNotFoundException("Relationship" + " with id: " + id + " not found");
}
if (relationship == null) {
throw new ResourceNotFoundException("Relationship" + " with id: " + id + " not found");
}
try {
RelationshipRest relationshipRest;
try {
relationshipRest = new ObjectMapper().readValue(jsonNode.toString(), RelationshipRest.class);
} catch (IOException e) {
throw new UnprocessableEntityException("Error parsing request body: " + e.toString());
}
relationship.setLeftwardValue(relationshipRest.getLeftwardValue());
relationship.setRightwardValue(relationshipRest.getRightwardValue());
if (jsonNode.hasNonNull("rightPlace")) {
relationship.setRightPlace(relationshipRest.getRightPlace());
}
if (jsonNode.hasNonNull("leftPlace")) {
relationship.setRightPlace(relationshipRest.getLeftPlace());
}
relationshipService.update(context, relationship);
context.commit();
context.reloadEntity(relationship);
return relationshipConverter.fromModel(relationship);
} catch (AuthorizeException e) {
throw new AccessDeniedException("You do not have write rights on this relationship's metadata");
}
}
/** /**
* This method will check with the current user has write rights on both one of the original items and one of the * This method will check with the current user has write rights on both one of the original items and one of the
* new items for the relationship. * new items for the relationship.
@@ -234,6 +306,7 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
} }
} }
/** /**
* This method will find all the Relationship objects that a RelationshipType that corresponds to the given Label * This method will find all the Relationship objects that a RelationshipType that corresponds to the given Label
* It's also possible to pass a DSO along to this method with a parameter which will only return Relationship * It's also possible to pass a DSO along to this method with a parameter which will only return Relationship
@@ -250,11 +323,12 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
public Page<RelationshipRest> findByLabel(@Parameter(value = "label", required = true) String label, public Page<RelationshipRest> findByLabel(@Parameter(value = "label", required = true) String label,
@Parameter(value = "dso", required = false) UUID dsoId, @Parameter(value = "dso", required = false) UUID dsoId,
Pageable pageable) throws SQLException { Pageable pageable) throws SQLException {
Context context = obtainContext(); Context context = obtainContext();
List<RelationshipType> relationshipTypeList = relationshipTypeService.findByLeftOrRightLabel(context, label); List<RelationshipType> relationshipTypeList =
relationshipTypeService.findByLeftwardOrRightwardTypeName(context, label);
List<Relationship> relationships = new LinkedList<>(); List<Relationship> relationships = new LinkedList<>();
int total = 0;
if (dsoId != null) { if (dsoId != null) {
Item item = itemService.find(context, dsoId); Item item = itemService.find(context, dsoId);
@@ -263,16 +337,20 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
throw new ResourceNotFoundException("The request DSO with id: " + dsoId + " was not found"); throw new ResourceNotFoundException("The request DSO with id: " + dsoId + " was not found");
} }
for (RelationshipType relationshipType : relationshipTypeList) { for (RelationshipType relationshipType : relationshipTypeList) {
relationships.addAll(relationshipService.findByItemAndRelationshipType(context, total = relationshipService.countByItemAndRelationshipType(context, item, relationshipType);
item, relationshipType)); relationships.addAll(relationshipService.findByItemAndRelationshipType(context, item, relationshipType,
pageable.getPageSize(), pageable.getOffset()));
} }
} else { } else {
for (RelationshipType relationshipType : relationshipTypeList) { for (RelationshipType relationshipType : relationshipTypeList) {
relationships.addAll(relationshipService.findByRelationshipType(context, relationshipType)); total = relationshipService.countByRelationshipType(context, relationshipType);
relationships.addAll(relationshipService.findByRelationshipType(context, relationshipType,
pageable.getPageSize(), pageable.getOffset()));
} }
} }
Page<RelationshipRest> page = utils.getPage(relationships, pageable).map(relationshipConverter); Page<RelationshipRest> page = new PageImpl<Relationship>(relationships,
pageable, total).map(relationshipConverter);
return page; return page;
} }

Some files were not shown because too many files have changed in this diff Show More