Merge remote-tracking branch 'dspace/master' into feature-external-sources

This commit is contained in:
Raf Ponsaerts
2019-11-26 09:29:07 +01:00
424 changed files with 18933 additions and 4574 deletions

View File

@@ -3,4 +3,9 @@
.settings/
*/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

@@ -54,7 +54,13 @@ EXPOSE 8080 8009
ENV JAVA_OPTS=-Xmx2000m
RUN mv /usr/local/tomcat/webapps/ROOT /usr/local/tomcat/webapps/ROOT.bk && \
ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/ROOT && \
ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/server && \
# Run the "server" webapp off the /server path (e.g. http://localhost:8080/server/)
# and the v6.x (deprecated) REST API off the "/rest" path
RUN ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/server && \
ln -s $DSPACE_INSTALL/webapps/rest /usr/local/tomcat/webapps/rest
# If you wish to run "server" webapp off the ROOT path, then comment out the above RUN, and uncomment the below RUN.
# You also MUST update the URL in dspace/src/main/docker/local.cfg
# Please note that server webapp should only run on one path at a time.
#RUN mv /usr/local/tomcat/webapps/ROOT /usr/local/tomcat/webapps/ROOT.bk && \
# ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/ROOT && \
# ln -s $DSPACE_INSTALL/webapps/rest /usr/local/tomcat/webapps/rest

View File

@@ -54,11 +54,17 @@ EXPOSE 8080 8009
ENV JAVA_OPTS=-Xmx2000m
RUN mv /usr/local/tomcat/webapps/ROOT /usr/local/tomcat/webapps/ROOT.bk && \
ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/ROOT && \
ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/server && \
# Run the "server" webapp off the /server path (e.g. http://localhost:8080/server/)
# and the v6.x (deprecated) REST API off the "/rest" path
RUN ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/server && \
ln -s $DSPACE_INSTALL/webapps/rest /usr/local/tomcat/webapps/rest
# If you wish to run "server" webapp off the ROOT path, then comment out the above RUN, and uncomment the below RUN.
# You also MUST update the URL in dspace/src/main/docker/local.cfg
# Please note that server webapp should only run on one path at a time.
#RUN mv /usr/local/tomcat/webapps/ROOT /usr/local/tomcat/webapps/ROOT.bk && \
# ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/ROOT && \
# ln -s $DSPACE_INSTALL/webapps/rest /usr/local/tomcat/webapps/rest
# Overwrite the v6.x (deprecated) REST API's web.xml, so that we can run it on HTTP (defaults to requiring HTTPS)
COPY dspace/src/main/docker/test/rest_web.xml $DSPACE_INSTALL/webapps/rest/WEB-INF/web.xml
RUN sed -i -e "s|\${dspace.dir}|$DSPACE_INSTALL|" $DSPACE_INSTALL/webapps/rest/WEB-INF/web.xml
RUN sed -i -e "s|\${dspace.dir}|$DSPACE_INSTALL|" $DSPACE_INSTALL/webapps/rest/WEB-INF/web.xml

View File

@@ -3,12 +3,12 @@
[![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 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)
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.
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.
* 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
**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.
@@ -31,21 +31,21 @@ Past releases are all available via GitHub at https://github.com/DSpace/DSpace/r
## 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:
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.
More information about these and all other prerequisites can be found in the Installation instructions above.
## Dockerfile Usage
See the [DSpace Docker Tutorial](https://dspace-labs.github.io/DSpace-Docker-Images/).
## Running DSpace 7 in Docker
See [Running DSpace 7 with Docker Compose](dspace/src/main/docker-compose/README.md)
## 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.
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
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
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
[Registered Service Providers](http://www.dspace.org/service-providers).
## 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
# NOTE: testClassName is just the class name, do not include package
mvn clean test -Dmaven.test.skip=false -Dtest=[testClassName]
# Run one test method in a specific test class
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: testClassName is just the class name, do not include package
mvn clean verify -Dmaven.test.skip=false -DskipITs=false -Dit.test=[testClassName]
# Run one test method in a specific test class
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
cd [dspace-src]
mvn clean install
# Then, move into a module subdirectory, and run the test command
cd [dspace-src]/dspace-server-webapp
# 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.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -38,7 +38,6 @@ import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Entity;
import org.dspace.content.EntityType;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchemaEnum;
@@ -106,19 +105,44 @@ public class MetadataImport {
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<>();
/**
* 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
*/
@@ -169,7 +193,7 @@ public class MetadataImport {
* @param workflowNotify If the workflows should be used, whether to send notifications or not
* @param useTemplate Use collection template if create new item
* @return An array of BulkEditChange elements representing the items that have changed
* @throws MetadataImportException if something goes wrong
* @throws MetadataImportException if something goes wrong
*/
public List<BulkEditChange> runImport(boolean change,
boolean useWorkflow,
@@ -184,10 +208,10 @@ public class MetadataImport {
c.setMode(Context.Mode.BATCH_EDIT);
// Process each change
int rowCount = 1;
rowCount = 1;
for (DSpaceCSVLine line : toImport) {
//Resolve references to other items
populateRefAndRowMap(line, rowCount, null);
// Resolve target references to other items
populateRefAndRowMap(line, line.getID());
line = resolveEntityRefs(line);
// Get the DSpace item to compare with
UUID id = line.getID();
@@ -201,7 +225,7 @@ public class MetadataImport {
WorkflowItem wfItem = null;
Item item = null;
// Is this a new item?
// Is this an existing item?
if (id != null) {
// Get the item
item = itemService.find(c, id);
@@ -238,9 +262,8 @@ public class MetadataImport {
}
}
}
// Compare
compare(item, fromCSV, change, md, whatHasChanged, line);
compareAndUpdate(item, fromCSV, change, md, whatHasChanged, line);
}
}
@@ -378,30 +401,25 @@ public class MetadataImport {
item = wsItem.getItem();
// Add the metadata to the item
List<BulkEditMetadataValue> relationships = new LinkedList<>();
for (BulkEditMetadataValue dcv : whatHasChanged.getAdds()) {
if (!StringUtils.equals(dcv.getSchema(), MetadataSchemaEnum.RELATION.getName())) {
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()) {
if (StringUtils.equals(dcv.getSchema(), MetadataSchemaEnum.RELATION.getName())) {
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());
addRelationship(c, item, dcv.getElement(), dcv.getValue());
}
}
for (BulkEditMetadataValue relationship : relationships) {
handleRelationshipMetadataValueFromBulkEditMetadataValue(item, relationship);
}
// Should the workflow be used?
if (useWorkflow) {
WorkflowService workflowService = WorkflowServiceFactory.getInstance().getWorkflowService();
@@ -424,8 +442,6 @@ public class MetadataImport {
}
}
// Commit changes to the object
// c.commit();
whatHasChanged.setItem(item);
}
@@ -439,7 +455,7 @@ public class MetadataImport {
c.uncacheEntity(wfItem);
c.uncacheEntity(item);
}
populateRefAndRowMap(line, rowCount, item == null ? null : item.getID());
populateRefAndRowMap(line, item == null ? null : item.getID());
// keep track of current rows processed
rowCount++;
}
@@ -452,32 +468,14 @@ public class MetadataImport {
}
// Return the changes
if (!change ) {
validateExpressedRelations();
}
return changes;
}
/**
* This metod handles the BulkEditMetadataValue objects that correspond to Relationship metadatavalues
* @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
* Compare an item metadata with a line from CSV, and optionally update the item.
*
* @param item The current item metadata
* @param fromCSV The metadata from the CSV file
@@ -487,9 +485,10 @@ public class MetadataImport {
* @param line line in CSV file
* @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 MetadataImportException custom exception for error handling within metadataimport
*/
protected void compare(Item item, String[] fromCSV, boolean change,
String md, BulkEditChange changes, DSpaceCSVLine line)
protected void compareAndUpdate(Item item, String[] fromCSV, boolean change,
String md, BulkEditChange changes, DSpaceCSVLine line)
throws SQLException, AuthorizeException, MetadataImportException {
// Log what metadata element we're looking at
String all = "";
@@ -663,10 +662,9 @@ public class MetadataImport {
}
}
if (StringUtils.equals(schema, MetadataSchemaEnum.RELATION.getName())) {
List<RelationshipType> relationshipTypeList = relationshipTypeService
.findByLeftOrRightLabel(c, element);
.findByLeftwardOrRightwardTypeName(c, element);
for (RelationshipType relationshipType : relationshipTypeList) {
for (Relationship relationship : relationshipService
.findByItemAndRelationshipType(c, item, relationshipType)) {
@@ -674,7 +672,7 @@ public class MetadataImport {
relationshipService.update(c, relationship);
}
}
handleRelationMetadata(c, item, schema, element, qualifier, language, values, authorities, confidences);
addRelationships(c, item, element, values);
} else {
itemService.clearMetadata(c, item, schema, element, qualifier, language);
itemService.addMetadata(c, item, schema, element, qualifier,
@@ -685,47 +683,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 item The item to which this metadatavalue belongs to
* @param schema The schema for the metadatavalue
* @param element The element for the metadatavalue
* @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
* @param typeName The element for the metadatavalue
* @param values to iterate over
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
private void handleRelationMetadata(Context c, Item item, String schema, String element, String qualifier,
String language, List<String> values, List<String> authorities,
List<Integer> confidences) throws SQLException, AuthorizeException,
private void addRelationships(Context c, Item item, String typeName, List<String> values)
throws SQLException, AuthorizeException,
MetadataImportException {
if (StringUtils.equals(element, "type") && StringUtils.isBlank(qualifier)) {
handleRelationTypeMetadata(c, item, schema, element, qualifier, language, values, authorities, confidences);
} else {
for (String value : values) {
handleRelationOtherMetadata(c, item, element, value);
}
for (String value : values) {
addRelationship(c, item, typeName, value);
}
}
/**
* Gets an existing entity from a reference.
* Gets an existing entity from a target reference.
*
* @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.
* @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;
UUID uuid = resolveEntityRef(context, reference);
UUID uuid = resolveEntityRef(context, targetReference);
// At this point, we have a uuid, so we can get an entity
try {
entity = entityService.findByItemId(context, uuid);
@@ -734,205 +720,73 @@ public class MetadataImport {
}
return entity;
} 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 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
* @throws SQLException 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 {
if (value.isEmpty()) {
return;
}
Entity entity = entityService.findByItemId(c, item.getID());
boolean left = false;
List<RelationshipType> acceptableRelationshipTypes = new LinkedList<>();
// Get entity from target reference
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);
List<RelationshipType> rightRelationshipTypesForEntity = entityService.getRightRelationshipTypes(c, entity);
// Get the correct RelationshipType based on typeName
List<RelationshipType> relType = relationshipTypeService.findByLeftwardOrRightwardTypeName(c, typeName);
RelationshipType foundRelationshipType = matchRelationshipType(relType,
relationEntityRelationshipType, itemRelationshipType, typeName);
for (RelationshipType relationshipType : entityService.getAllRelationshipTypes(c, entity)) {
if (StringUtils.equalsIgnoreCase(relationshipType.getLeftLabel(), element)) {
left = handleLeftLabelEqualityRelationshipTypeElement(c, entity, relationEntity, left,
acceptableRelationshipTypes,
leftRelationshipTypesForEntity,
relationshipType);
} else if (StringUtils.equalsIgnoreCase(relationshipType.getRightLabel(), element)) {
left = handleRightLabelEqualityRelationshipTypeElement(c, entity, relationEntity, left,
acceptableRelationshipTypes,
rightRelationshipTypesForEntity,
relationshipType);
}
if (foundRelationshipType == null) {
throw new MetadataImportException("Error on CSV row " + rowCount + ":" + "\n" +
"No Relationship type found for:\n" +
"Target type: " + relationEntityRelationshipType + "\n" +
"Origin referer type: " + itemRelationshipType + "\n" +
"with typeName: " + typeName);
}
if (acceptableRelationshipTypes.size() > 1) {
log.error("Ambiguous relationship_types were found");
return;
}
if (acceptableRelationshipTypes.size() == 0) {
log.error("no relationship_types were found");
return;
if (foundRelationshipType.getLeftwardType().equalsIgnoreCase(typeName)) {
left = true;
}
//There is exactly one
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 {
// Placeholder items for relation placing
Item leftItem = null;
Item rightItem = null;
if (left) {
leftItem = item;
rightItem = otherItem;
rightItem = relationEntity.getItem();
} else {
leftItem = relationEntity.getItem();
rightItem = item;
leftItem = otherItem;
}
RelationshipType relationshipType = acceptedRelationshipType;
int leftPlace = relationshipService.findLeftPlaceByLeftItem(c, leftItem) + 1;
int rightPlace = relationshipService.findRightPlaceByRightItem(c, rightItem) + 1;
// Create the relationship
int leftPlace = relationshipService.findNextLeftPlaceByLeftItem(c, leftItem);
int rightPlace = relationshipService.findNextRightPlaceByRightItem(c, rightItem);
Relationship persistedRelationship = relationshipService.create(c, leftItem, rightItem,
relationshipType, leftPlace, rightPlace);
foundRelationshipType, leftPlace, rightPlace);
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
* and what is in the CSV file
@@ -1573,9 +1427,6 @@ public class MetadataImport {
// Display the changes
displayChanges(changes, true);
// Commit the change to the DB
// c.commit();
}
// Finsh off and tidy up
@@ -1590,24 +1441,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.
*
* @param line the csv line to process.
* @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 {
DSpaceCSVLine newLine = new DSpaceCSVLine(line.getID());
UUID originId = evaluateOriginId(line.getID());
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 (line.get(key).size() > 0) {
for (String val : line.get(key)) {
// Attempt to resolve the relation reference
// These can be a UUID, metadata reference or rowName reference
// Attempt to resolve the relation target reference
// These can be a UUID, metadata target reference or rowName target reference
String uuid = resolveEntityRef(c, val).toString();
newLine.add(key, uuid);
//Entity refs have been resolved / placeholdered
//Populate the EntityRelationMap
populateEntityRelationMap(uuid, key, originId.toString());
}
}
} else {
@@ -1622,27 +1477,59 @@ public class MetadataImport {
}
}
}
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
* 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
* 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.
*
* @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.
*/
private void populateRefAndRowMap(DSpaceCSVLine line, int rowNumber, @Nullable UUID uuid) {
private void populateRefAndRowMap(DSpaceCSVLine line, @Nullable UUID uuid) {
if (uuid != null) {
csvRowMap.put(rowNumber, uuid);
csvRowMap.put(rowCount, uuid);
} else {
csvRowMap.put(rowCount, new UUID(0, rowCount));
}
for (String key : line.keys()) {
if (key.contains(".") && !key.split("\\.")[0].equalsIgnoreCase("relation") ||
@@ -1654,22 +1541,31 @@ public class MetadataImport {
rowNums = new HashSet<>();
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.
*
* 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 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.
* @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 {
// value reference
@@ -1679,7 +1575,8 @@ public class MetadataImport {
try {
return UUID.fromString(reference);
} 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
MetadataValueService metadataValueService = ContentServiceFactory.getInstance().getMetadataValueService();
@@ -1689,7 +1586,8 @@ public class MetadataImport {
String mfValue = reference.substring(i + 1);
String mf[] = reference.substring(0, i).split("\\.");
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])");
}
String schema = mf[0];
@@ -1702,11 +1600,13 @@ public class MetadataImport {
MetadataValue mdvVal = mdv.next();
uuid = mdvVal.getDSpaceObject().getID();
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) {
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
@@ -1714,20 +1614,23 @@ public class MetadataImport {
// See getMatchingCSVUUIDs() for how the reference param is sourced from the csvRefMap
Set<UUID> csvUUIDs = getMatchingCSVUUIDs(reference);
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) {
UUID csvUUID = csvUUIDs.iterator().next();
if (csvUUID.equals(uuid)) {
return uuid; // one match from csv and db (same item)
} 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 {
return csvUUID; // one match from csv
}
} else { // size == 0; the reference does not exist throw an error
if (uuid == null) {
throw new MetadataImportException("No matches found for reference: " + reference
+ ", Keep in mind you can only reference entries that are listed before " +
throw new MetadataImportException("Error in CSV row " + rowCount + ":\n" +
"No matches found for reference: " + reference
+ "\nKeep in mind you can only reference entries that are listed before " +
"this one within the CSV.");
} else {
return uuid; // one match from db
@@ -1767,4 +1670,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;
}
} else {
// not a handle, try and treat it as an integer collection database ID
System.out.println("Looking up by id: " + collectionID + ", parsed as '" + Integer
.parseInt(collectionID) + "', " + "in context: " + context);
// not a handle, try and treat it as an collection database UUID
System.out.println("Looking up by UUID: " + collectionID + ", " + "in context: " + context);
targetCollection = collectionService.find(context, UUID.fromString(collectionID));
}
}
@@ -460,7 +459,7 @@ public class Harvest {
List<String> errors;
System.out.print("Testing basic PMH access: ");
errors = OAIHarvester.verifyOAIharvester(server, set,
errors = harvestedCollectionService.verifyOAIharvester(server, set,
(null != metadataFormat) ? metadataFormat : "dc", false);
if (errors.isEmpty()) {
System.out.println("OK");
@@ -471,7 +470,7 @@ public class Harvest {
}
System.out.print("Testing ORE support: ");
errors = OAIHarvester.verifyOAIharvester(server, set,
errors = harvestedCollectionService.verifyOAIharvester(server, set,
(null != metadataFormat) ? metadataFormat : "dc", true);
if (errors.isEmpty()) {
System.out.println("OK");

View File

@@ -13,6 +13,12 @@ import java.lang.reflect.Method;
import java.util.List;
import java.util.TreeMap;
import org.apache.commons.cli.ParseException;
import org.apache.log4j.Logger;
import org.dspace.scripts.DSpaceRunnable;
import org.dspace.scripts.factory.ScriptServiceFactory;
import org.dspace.scripts.handler.DSpaceRunnableHandler;
import org.dspace.scripts.handler.impl.CommandLineDSpaceRunnableHandler;
import org.dspace.servicemanager.DSpaceKernelImpl;
import org.dspace.servicemanager.DSpaceKernelInit;
import org.dspace.services.RequestService;
@@ -27,6 +33,9 @@ import org.jdom.input.SAXBuilder;
* @author Mark Diggory
*/
public class ScriptLauncher {
private static final Logger log = Logger.getLogger(ScriptLauncher.class);
/**
* The service manager kernel
*/
@@ -76,8 +85,9 @@ public class ScriptLauncher {
}
// Look up command in the configuration, and execute.
int status;
status = runOneCommand(commandConfigs, args);
CommandLineDSpaceRunnableHandler commandLineDSpaceRunnableHandler = new CommandLineDSpaceRunnableHandler();
int status = handleScript(args, commandConfigs, commandLineDSpaceRunnableHandler, kernelImpl);
// Destroy the service kernel if it is still alive
if (kernelImpl != null) {
@@ -86,6 +96,50 @@ public class ScriptLauncher {
}
System.exit(status);
}
/**
* This method will take the arguments from a commandline input and it'll find the script that the first argument
* refers to and it'll execute this script.
* It can return a 1 or a 0 depending on whether the script failed or passed respectively
* @param args The arguments for the script and the script as first one in the array
* @param commandConfigs The Document
* @param dSpaceRunnableHandler The DSpaceRunnableHandler for this execution
* @param kernelImpl The relevant DSpaceKernelImpl
* @return A 1 or 0 depending on whether the script failed or passed respectively
*/
public static int handleScript(String[] args, Document commandConfigs,
DSpaceRunnableHandler dSpaceRunnableHandler,
DSpaceKernelImpl kernelImpl) {
int status;
DSpaceRunnable script = ScriptServiceFactory.getInstance().getScriptService().getScriptForName(args[0]);
if (script != null) {
status = executeScript(args, dSpaceRunnableHandler, script);
} else {
status = runOneCommand(commandConfigs, args, kernelImpl);
}
return status;
}
/**
* This method will simply execute the script
* @param args The arguments of the script with the script name as first place in the array
* @param dSpaceRunnableHandler The relevant DSpaceRunnableHandler
* @param script The script to be executed
* @return A 1 or 0 depending on whether the script failed or passed respectively
*/
private static int executeScript(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
DSpaceRunnable script) {
try {
script.initialize(args, dSpaceRunnableHandler);
script.run();
return 0;
} catch (ParseException e) {
script.printHelp();
e.printStackTrace();
return 1;
}
}
protected static int runOneCommand(Document commandConfigs, String[] args) {
@@ -98,7 +152,7 @@ public class ScriptLauncher {
* @param commandConfigs Document
* @param args the command line arguments given
*/
public static int runOneCommand(Document commandConfigs, String[] args, DSpaceKernelImpl kernelImpl) {
protected static int runOneCommand(Document commandConfigs, String[] args, DSpaceKernelImpl kernelImpl) {
String request = args[0];
Element root = commandConfigs.getRootElement();
List<Element> commands = root.getChildren("command");

View File

@@ -89,6 +89,11 @@ public class DCInput {
*/
private boolean repeatable = false;
/**
* should name-variants be used?
*/
private boolean nameVariants = false;
/**
* 'hint' text to display
*/
@@ -183,6 +188,9 @@ public class DCInput {
String repStr = fieldMap.get("repeatable");
repeatable = "true".equalsIgnoreCase(repStr)
|| "yes".equalsIgnoreCase(repStr);
String nameVariantsString = fieldMap.get("name-variants");
nameVariants = (StringUtils.isNotBlank(nameVariantsString)) ?
nameVariantsString.equalsIgnoreCase("true") : false;
label = fieldMap.get("label");
inputType = fieldMap.get("input-type");
// these types are list-controlled
@@ -269,6 +277,15 @@ public class DCInput {
return isRepeatable();
}
/**
* Get the nameVariants flag for this row
*
* @return the nameVariants flag
*/
public boolean areNameVariantsAllowed() {
return nameVariants;
}
/**
* Get the input type for this row
*

View File

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

View File

@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.List;
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.SolrServerException;
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.
*/
protected HttpSolrClient solr = null;
protected SolrClient solr = null;
protected HttpSolrClient getSolr()
protected SolrClient getSolr()
throws MalformedURLException, SolrServerException, IOException {
if (solr == null) {
@@ -49,12 +50,14 @@ public class AuthoritySolrServiceImpl implements AuthorityIndexingService, Autho
log.debug("Solr authority URL: " + solrService);
solr = new HttpSolrClient.Builder(solrService).build();
solr.setBaseURL(solrService);
HttpSolrClient solrServer = new HttpSolrClient.Builder(solrService).build();
solrServer.setBaseURL(solrService);
SolrQuery solrQuery = new SolrQuery().setQuery("*:*");
solr.query(solrQuery);
solrServer.query(solrQuery);
solr = solrServer;
}
return solr;

View File

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

View File

@@ -7,6 +7,10 @@
*/
package org.dspace.content;
import static org.dspace.core.Constants.ADD;
import static org.dspace.core.Constants.REMOVE;
import static org.dspace.core.Constants.WRITE;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
@@ -268,6 +272,81 @@ public class BundleServiceImpl extends DSpaceObjectServiceImpl<Bundle> implement
return authorizeService.getPolicies(context, bundle);
}
@Override
public void updateBitstreamOrder(Context context, Bundle bundle, int from, int to)
throws AuthorizeException, SQLException {
List<Bitstream> bitstreams = bundle.getBitstreams();
if (bitstreams.size() < 1 || from >= bitstreams.size() || to >= bitstreams.size() || from < 0 || to < 0) {
throw new IllegalArgumentException(
"Invalid 'from' and 'to' arguments supplied for moving a bitstream within bundle " +
bundle.getID() + ". from: " + from + "; to: " + to
);
}
List<UUID> bitstreamIds = new LinkedList<>();
for (Bitstream bitstream : bitstreams) {
bitstreamIds.add(bitstream.getID());
}
if (from < to) {
bitstreamIds.add(to + 1, bitstreamIds.get(from));
bitstreamIds.remove(from);
} else {
bitstreamIds.add(to, bitstreamIds.get(from));
bitstreamIds.remove(from + 1);
}
setOrder(context, bundle, bitstreamIds.toArray(new UUID[bitstreamIds.size()]));
}
@Override
public void moveBitstreamToBundle(Context context, Bundle targetBundle, Bitstream bitstream)
throws SQLException, AuthorizeException, IOException {
List<Bundle> bundles = new LinkedList<>();
bundles.addAll(bitstream.getBundles());
if (hasSufficientMovePermissions(context, bundles, targetBundle)) {
this.addBitstream(context, targetBundle, bitstream);
this.update(context, targetBundle);
for (Bundle bundle : bundles) {
this.removeBitstream(context, bundle, bitstream);
this.update(context, bundle);
}
}
}
/**
* Verifies if the context (user) has sufficient rights to the bundles in order to move a bitstream
*
* @param context The context
* @param bundles The current bundles in which the bitstream resides
* @param targetBundle The target bundle
* @return true when the context has sufficient rights
* @throws AuthorizeException When one of the necessary rights is not present
*/
private boolean hasSufficientMovePermissions(final Context context, final List<Bundle> bundles,
final Bundle targetBundle) throws SQLException, AuthorizeException {
for (Bundle bundle : bundles) {
if (!authorizeService.authorizeActionBoolean(context, bundle, WRITE) || !authorizeService
.authorizeActionBoolean(context, bundle, REMOVE)) {
throw new AuthorizeException(
"The current user does not have WRITE and REMOVE access to the current bundle: " + bundle
.getID());
}
}
if (!authorizeService.authorizeActionBoolean(context, targetBundle, WRITE) || !authorizeService
.authorizeActionBoolean(context, targetBundle, ADD)) {
throw new AuthorizeException(
"The current user does not have WRITE and ADD access to the target bundle: " + targetBundle
.getID());
}
for (Item item : targetBundle.getItems()) {
if (!authorizeService.authorizeActionBoolean(context, item, WRITE)) {
throw new AuthorizeException(
"The current user does not have WRITE access to the target bundle's item: " + item.getID());
}
}
return true;
}
@Override
public void setOrder(Context context, Bundle bundle, UUID[] bitstreamIds) throws AuthorizeException, SQLException {
authorizeService.authorizeAction(context, bundle, Constants.WRITE);

View File

@@ -146,7 +146,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
public List<MetadataValue> getMetadataByMetadataString(T dso, String mdString) {
StringTokenizer dcf = new StringTokenizer(mdString, ".");
String[] tokens = { "", "", "" };
String[] tokens = {"", "", ""};
int i = 0;
while (dcf.hasMoreTokens()) {
tokens[i] = dcf.nextToken().trim();
@@ -250,8 +250,11 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
}
}
MetadataValue metadataValue = metadataValueService.create(context, dso, metadataField);
//Set place to list length
metadataValue.setPlace(this.getMetadata(dso, Item.ANY, Item.ANY, Item.ANY, Item.ANY).size());
//Set place to list length of all metadatavalues for the given schema.element.qualifier combination.
// Subtract one to adhere to the 0 as first element rule
metadataValue.setPlace(
this.getMetadata(dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(),
metadataField.getQualifier(), Item.ANY).size() - 1);
metadataValue.setLanguage(lang == null ? null : lang.trim());
@@ -533,7 +536,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
protected String[] getMDValueByField(String field) {
StringTokenizer dcf = new StringTokenizer(field, ".");
String[] tokens = { "", "", "" };
String[] tokens = {"", "", ""};
int i = 0;
while (dcf.hasMoreTokens()) {
tokens[i] = dcf.nextToken().trim();
@@ -571,7 +574,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
if (compare == 0) {
if (o1 instanceof RelationshipMetadataValue) {
return 1;
} else if (o2 instanceof RelationshipMetadataValue) {
} else if (o2 instanceof RelationshipMetadataValue) {
return -1;
}
}

View File

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

View File

@@ -13,11 +13,9 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
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.RelationshipService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.content.virtual.VirtualMetadataConfiguration;
import org.dspace.content.virtual.VirtualMetadataPopulator;
import org.dspace.core.Constants;
import org.dspace.core.Context;
@@ -117,6 +114,9 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
@Autowired(required = true)
protected VirtualMetadataPopulator virtualMetadataPopulator;
@Autowired(required = true)
private RelationshipMetadataService relationshipMetadataService;
protected ItemServiceImpl() {
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);
}
@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
public List<MetadataValue> getMetadata(Item item, String schema, String element, String qualifier, String lang,
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
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<>();
for (MetadataValue metadataValue : relationMetadata) {
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<>();
if (enableVirtualMetadata) {
fullMetadataValueList.addAll(getRelationshipMetadata(item, true));
fullMetadataValueList.addAll(relationshipMetadataService.getRelationshipMetadata(item, true));
}
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,
* MetadataField Qualifier and MetadataField Place in that order.
* @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) {
Comparator<MetadataValue> comparator = Comparator.comparing(
@@ -1427,137 +1407,5 @@ prevent the generation of resource policy entry values with null dspace_object a
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

@@ -0,0 +1,19 @@
/**
* 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;
/**
* This Enum holds a representation of all the possible states that a Process can be in
*/
public enum ProcessStatus {
SCHEDULED,
RUNNING,
COMPLETED,
FAILED
}

View File

@@ -77,6 +77,18 @@ public class Relationship implements ReloadableEntity<Integer> {
@Column(name = "right_place")
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:
* {@link org.dspace.content.service.RelationshipService#create(Context)} }
@@ -170,6 +182,38 @@ public class Relationship implements ReloadableEntity<Integer> {
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
* @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.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
@@ -59,12 +58,21 @@ public class RelationshipServiceImpl implements RelationshipService {
@Override
public Relationship create(Context c, Item leftItem, Item rightItem, RelationshipType relationshipType,
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.setLeftItem(leftItem);
relationship.setRightItem(rightItem);
relationship.setRelationshipType(relationshipType);
relationship.setLeftPlace(leftPlace);
relationship.setRightPlace(rightPlace);
relationship.setLeftwardValue(leftwardValue);
relationship.setRightwardValue(rightwardValue);
return create(c, relationship);
}
@@ -73,8 +81,12 @@ public class RelationshipServiceImpl implements RelationshipService {
if (isRelationshipValidToCreate(context, relationship)) {
if (authorizeService.authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE) ||
authorizeService.authorizeActionBoolean(context, relationship.getRightItem(), Constants.WRITE)) {
updatePlaceInRelationship(context, relationship, true);
return relationshipDAO.create(context, relationship);
// This order of execution should be handled in the creation (create, updateplace, update relationship)
// for a proper place allocation
Relationship relationshipToReturn = relationshipDAO.create(context, relationship);
updatePlaceInRelationship(context, relationshipToReturn);
update(context, relationshipToReturn);
return relationshipToReturn;
} else {
throw new AuthorizeException(
"You do not have write rights on this relationship's items");
@@ -86,20 +98,36 @@ public class RelationshipServiceImpl implements RelationshipService {
}
@Override
public void updatePlaceInRelationship(Context context, Relationship relationship, boolean isCreation)
public void updatePlaceInRelationship(Context context, Relationship relationship)
throws SQLException, AuthorizeException {
Item leftItem = relationship.getLeftItem();
// Max value is used to ensure that these will get added to the back of the list and thus receive the highest
// (last) place as it's set to a -1 for creation
if (relationship.getLeftPlace() == -1) {
relationship.setLeftPlace(Integer.MAX_VALUE);
}
Item rightItem = relationship.getRightItem();
if (relationship.getRightPlace() == -1) {
relationship.setRightPlace(Integer.MAX_VALUE);
}
List<Relationship> leftRelationships = findByItemAndRelationshipType(context,
leftItem,
relationship.getRelationshipType(), true);
Item rightItem = relationship.getRightItem();
List<Relationship> rightRelationships = findByItemAndRelationshipType(context,
rightItem,
relationship.getRelationshipType(),
false);
// These relationships are only deleted from the temporary lists incase they're present in them so that we can
// properly perform our place calculation later down the line in this method.
if (leftRelationships.contains(relationship)) {
leftRelationships.remove(relationship);
}
if (rightRelationships.contains(relationship)) {
rightRelationships.remove(relationship);
}
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.
if (!virtualMetadataPopulator.isUseForPlaceTrueForRelationshipType(relationship.getRelationshipType(), true)) {
if (!leftRelationships.isEmpty()) {
@@ -116,7 +144,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.
if (!virtualMetadataPopulator.isUseForPlaceTrueForRelationshipType(relationship.getRelationshipType(), false)) {
if (!rightRelationships.isEmpty()) {
@@ -133,10 +161,6 @@ public class RelationshipServiceImpl implements RelationshipService {
updateItem(context, rightItem);
}
if (isCreation) {
handleCreationPlaces(context, relationship);
}
context.restoreAuthSystemState();
}
@@ -148,43 +172,14 @@ public class RelationshipServiceImpl implements RelationshipService {
itemService.update(context, relatedItem);
}
//Sets the places for the Relationship properly if the updatePlaceInRelationship was called for a new creation
//of this Relationship
private void handleCreationPlaces(Context context, Relationship relationship) throws SQLException {
List<Relationship> leftRelationships;
List<Relationship> rightRelationships;
leftRelationships = findByItemAndRelationshipType(context,
relationship.getLeftItem(),
relationship.getRelationshipType(), true);
rightRelationships = findByItemAndRelationshipType(context,
relationship.getRightItem(),
relationship.getRelationshipType(),
false);
leftRelationships.sort((o1, o2) -> o2.getLeftPlace() - o1.getLeftPlace());
rightRelationships.sort((o1, o2) -> o2.getRightPlace() - o1.getRightPlace());
if (!leftRelationships.isEmpty()) {
relationship.setLeftPlace(leftRelationships.get(0).getLeftPlace() + 1);
} else {
relationship.setLeftPlace(0);
}
if (!rightRelationships.isEmpty()) {
relationship.setRightPlace(rightRelationships.get(0).getRightPlace() + 1);
} else {
relationship.setRightPlace(0);
}
@Override
public int findNextLeftPlaceByLeftItem(Context context, Item item) throws SQLException {
return relationshipDAO.findNextLeftPlaceByLeftItem(context, item);
}
@Override
public int findLeftPlaceByLeftItem(Context context, Item item) throws SQLException {
return relationshipDAO.findLeftPlaceByLeftItem(context, item);
}
@Override
public int findRightPlaceByRightItem(Context context, Item item) throws SQLException {
return relationshipDAO.findRightPlaceByRightItem(context, item);
public int findNextRightPlaceByRightItem(Context context, Item item) throws SQLException {
return relationshipDAO.findNextRightPlaceByRightItem(context, item);
}
private boolean isRelationshipValidToCreate(Context context, Relationship relationship) throws SQLException {
@@ -221,8 +216,8 @@ public class RelationshipServiceImpl implements RelationshipService {
private void logRelationshipTypeDetailsForError(RelationshipType relationshipType) {
log.warn("The relationshipType's ID is: " + relationshipType.getID());
log.warn("The relationshipType's left label is: " + relationshipType.getLeftLabel());
log.warn("The relationshipType's right label is: " + relationshipType.getRightLabel());
log.warn("The relationshipType's leftward type is: " + relationshipType.getLeftwardType());
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 right entityType label is: " + relationshipType.getRightType().getLabel());
log.warn("The relationshipType's left min cardinality is: " + relationshipType.getLeftMinCardinality());
@@ -259,11 +254,18 @@ public class RelationshipServiceImpl implements RelationshipService {
@Override
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) -> {
int relationshipType = o1.getRelationshipType().getLeftLabel()
.compareTo(o2.getRelationshipType().getLeftLabel());
int relationshipType = o1.getRelationshipType().getLeftwardType()
.compareTo(o2.getRelationshipType().getLeftwardType());
if (relationshipType != 0) {
return relationshipType;
} else {
@@ -279,7 +281,12 @@ public class RelationshipServiceImpl implements RelationshipService {
@Override
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
@@ -311,7 +318,7 @@ public class RelationshipServiceImpl implements RelationshipService {
if (authorizeService.authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE) ||
authorizeService.authorizeActionBoolean(context, relationship.getRightItem(), Constants.WRITE)) {
relationshipDAO.delete(context, relationship);
updatePlaceInRelationship(context, relationship, false);
updatePlaceInRelationship(context, relationship);
} else {
throw new AuthorizeException(
"You do not have write rights on this relationship's items");
@@ -359,8 +366,8 @@ public class RelationshipServiceImpl implements RelationshipService {
private boolean checkMinCardinality(Context context, Item item,
Relationship relationship,
Integer minCardinality, boolean isLeft) throws SQLException {
List<Relationship> list = this
.findByItemAndRelationshipType(context, item, relationship.getRelationshipType(), isLeft);
List<Relationship> list = this.findByItemAndRelationshipType(context, item, relationship.getRelationshipType(),
isLeft, -1, -1);
if (minCardinality != null && !(list.size() > minCardinality)) {
return false;
}
@@ -369,46 +376,83 @@ public class RelationshipServiceImpl implements RelationshipService {
public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType, boolean isLeft)
throws SQLException {
List<Relationship> list = this.findByItem(context, item);
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;
return this.findByItemAndRelationshipType(context, item, relationshipType, isLeft, -1, -1);
}
@Override
public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType)
throws SQLException {
List<Relationship> list = this.findByItem(context, item);
List<Relationship> listToReturn = new LinkedList<>();
for (Relationship relationship : list) {
if (relationship.getRelationshipType().equals(relationshipType)) {
listToReturn.add(relationship);
}
}
return listToReturn;
return relationshipDAO.findByItemAndRelationshipType(context, item, relationshipType, -1, -1);
}
@Override
public List<Relationship> findByItemAndRelationshipType(Context context, Item item,
RelationshipType relationshipType, int limit, int offset)
throws SQLException {
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
public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType)
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
* This class contains an Integer ID that will be the unique value and primary key in the database.
* This key is automatically generated
* It also has a leftType and rightType EntityType that describes the relationshipType together with a leftLabel and
* rightLabel.
* It also has a leftType and rightType EntityType that describes the relationshipType together with a leftwardType and
* rightwardType.
* The cardinality properties describe how many of each relations this relationshipType can support
*/
@Entity
@@ -61,20 +61,20 @@ public class RelationshipType implements ReloadableEntity<Integer> {
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 a textual representation of the name of the relationship that this RelationshipType is connected to
*/
@Column(name = "left_label", nullable = false)
private String leftLabel;
@Column(name = "leftward_type", nullable = false)
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 a textual representation of the name of the relationship that this RelationshipType is connected to
*/
@Column(name = "right_label", nullable = false)
private String rightLabel;
@Column(name = "rightward_type", nullable = false)
private String rightwardType;
/**
* 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
* @return The leftLabel String of this RelationshipType
* Standard getter for the leftwardType String for this RelationshipType
* @return The leftwardType String of this RelationshipType
*/
public String getLeftLabel() {
return leftLabel;
public String getLeftwardType() {
return leftwardType;
}
/**
* Standard setter for the leftLabel String for this RelationshipType
* @param leftLabel The leftLabel String that this RelationshipType should receive
* Standard setter for the leftwardType String for this RelationshipType
* @param leftwardType The leftwardType String that this RelationshipType should receive
*/
public void setLeftLabel(String leftLabel) {
this.leftLabel = leftLabel;
public void setLeftwardType(String leftwardType) {
this.leftwardType = leftwardType;
}
/**
* Standard getter for the rightLabel String for this RelationshipType
* @return The rightLabel String of this RelationshipType
* Standard getter for the rightwardType String for this RelationshipType
* @return The rightwardType String of this RelationshipType
*/
public String getRightLabel() {
return rightLabel;
public String getRightwardType() {
return rightwardType;
}
/**
* Standard setter for the rightLabel String for this RelationshipType
* @param rightLabel The rightLabel String that this RelationshipType should receive
* Standard setter for the rightwardType String for this RelationshipType
* @param rightwardType The rightwardType String that this RelationshipType should receive
*/
public void setRightLabel(String rightLabel) {
this.rightLabel = rightLabel;
public void setRightwardType(String rightwardType) {
this.rightwardType = rightwardType;
}
/**

View File

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

View File

@@ -220,6 +220,11 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
return controller;
}
@Override
public void clearCache() {
controller.clear();
authorities.clear();
}
private void loadChoiceAuthorityConfigurations() {
// Get all configuration keys starting with a given 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) {
log.warn(e.getMessage(), e);
}
return new Choice("", "", "");
return null;
}
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()) {
Choice[] results = new Choice[choices.size() - 1];
Choice[] results = new Choice[choices.size()];
choices.toArray(results);
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) {
return searchField + ":\"" + text.toLowerCase().replaceAll(":", "\\:") + "*\" or " + searchField + ":\"" + text
.toLowerCase().replaceAll(":", "\\:") + "\"";
return searchField + ":(" + text.toLowerCase().replaceAll(":", "\\:") + "*) or " + searchField + ":(" + text
.toLowerCase().replaceAll(":", "\\:") + ")";
}
@Override

View File

@@ -168,4 +168,9 @@ public interface ChoiceAuthorityService {
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

@@ -0,0 +1,57 @@
/**
* 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 java.sql.SQLException;
import java.util.List;
import org.dspace.core.Context;
import org.dspace.core.GenericDAO;
import org.dspace.scripts.Process;
/**
* This is the Data Access Object for the {@link Process} object
*/
public interface ProcessDAO extends GenericDAO<Process> {
/**
* This method will return all the Process objects in the database in a list and it'll be sorted by script name
* @param context The relevant DSpace context
* @return The list of all Process objects in the database sorted on scriptname
* @throws SQLException If something goes wrong
*/
public List<Process> findAllSortByScript(Context context) throws SQLException;
/**
* This method will return all the Process objects in the database in a list and it'll be sorted by start time.
* The most recent one will be shown first
* @param context The relevant DSpace context
* @return The list of all Process objects in the database sorted by starttime
* @throws SQLException If something goes wrong
*/
public List<Process> findAllSortByStartTime(Context context) throws SQLException;
/**
* Returns a list of all Process objects in the database
* @param context The relevant DSpace context
* @param limit The limit for the amount of Processes returned
* @param offset The offset for the Processes to be returned
* @return The list of all Process objects in the Database
* @throws SQLException If something goes wrong
*/
List<Process> findAll(Context context, int limit, int offset) throws SQLException;
/**
* Returns the total amount of Process objects in the dataase
* @param context The relevant DSpace context
* @return An integer that describes the amount of Process objects in the database
* @throws SQLException If something goes wrong
*/
int countRows(Context context) throws SQLException;
}

View File

@@ -34,29 +34,43 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
* right item that is equal to the given item
* @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 the highest leftplace integer for all the relationships where this
* item is the leftitem so that we can set a proper leftplace attribute on the next relationship
* 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 next leftplace integer to use for a relationship with this item as the leftItem
*
* @param context The relevant DSpace context
* @param item The item to be matched on leftItem
* @return The integer for the highest leftPlace value for all the relatonship objects
* that have the given item as leftItem
* @return The next integer to be used for the leftplace of a relationship with the given item
* as a left item
* @throws SQLException If something goes wrong
*/
int findLeftPlaceByLeftItem(Context context,Item item) throws SQLException;
int findNextLeftPlaceByLeftItem(Context context, Item item) throws SQLException;
/**
* This method returns the highest rightplace integer for all the relationships where this
* item is the rightitem so that we can set a proper rightplace attribute on the next relationship
* This method returns the next rightplace integer to use for a relationship with this item as the rightItem
*
* @param context The relevant DSpace context
* @param item The item to be matched on rightItem
* @return The integer for the highest rightPlace value for all the relatonship objects
* that have the given item as rightItem
* @return The next integer to be used for the rightplace of a relationship with the given item
* as a right item
* @throws SQLException If something goes wrong
*/
int findRightPlaceByRightItem(Context context,Item item) throws SQLException;
int findNextRightPlaceByRightItem(Context context, Item item) throws SQLException;
/**
* This method returns a list of Relationship objects for the given RelationshipType object.
@@ -69,4 +83,131 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
* @throws SQLException If something goes wrong
*/
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
* leftType, rightType, leftLabel and rightLabel as given in the parameters
* @param context The relevant DSpace context
* @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 leftLabel The leftLabel String to be matched in the query
* @param rightLabel The rightLabel String to be matched in the query
* @return The RelationshipType object that matches all the given parameters
* leftType, rightType, leftwardType and rightwardType as given in the parameters
* @param context The relevant DSpace context
* @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 leftwardType The leftwardType 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
* @throws SQLException If something goes wrong
*/
RelationshipType findByTypesAndLabels(Context context,
EntityType leftType,EntityType rightType,String leftLabel,String rightLabel)
throws SQLException;
RelationshipType findbyTypesAndTypeName(Context context, EntityType leftType,EntityType rightType,
String leftwardType,
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
* either the leftLabel or rightLabel.
* @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
* @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
@@ -58,4 +74,50 @@ public interface RelationshipTypeDAO extends GenericDAO<RelationshipType> {
* @throws SQLException If something goes wrong
*/
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

@@ -9,7 +9,6 @@ package org.dspace.content.dao.impl;
import java.sql.SQLException;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -64,11 +63,20 @@ public class CollectionDAOImpl extends AbstractHibernateDSODAO<Collection> imple
public List<Collection> findAll(Context context, MetadataField order, Integer limit, Integer offset)
throws SQLException {
StringBuilder query = new StringBuilder();
query.append("SELECT ").append(Collection.class.getSimpleName()).append(" FROM Collection as ")
.append(Collection.class.getSimpleName()).append(" ");
addMetadataLeftJoin(query, Collection.class.getSimpleName(), Arrays.asList(order));
addMetadataSortQuery(query, Arrays.asList(order), null);
// The query has to be rather complex because we want to sort the retrieval of Collections based on the title
// We'll join the Collections 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
query.append("SELECT c" +
" FROM Collection 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 hibernateQuery = createQuery(context, query.toString());
if (offset != null) {
hibernateQuery.setFirstResult(offset);
@@ -76,7 +84,7 @@ public class CollectionDAOImpl extends AbstractHibernateDSODAO<Collection> imple
if (limit != null) {
hibernateQuery.setMaxResults(limit);
}
hibernateQuery.setParameter(order.toString(), order.getID());
hibernateQuery.setParameter("sortField", order);
return list(hibernateQuery);
}

View File

@@ -8,8 +8,6 @@
package org.dspace.content.dao.impl;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
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)
throws SQLException {
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());
if (offset != null) {
query.setFirstResult(offset);
@@ -74,7 +81,8 @@ public class CommunityDAOImpl extends AbstractHibernateDSODAO<Community> impleme
if (limit != null) {
query.setMaxResults(limit);
}
query.setParameter(sortField.toString(), sortField.getID());
query.setParameter("sortField", sortField);
return list(query);
}
@@ -91,16 +99,26 @@ public class CommunityDAOImpl extends AbstractHibernateDSODAO<Community> impleme
@Override
public List<Community> findAllNoParent(Context context, MetadataField sortField) throws SQLException {
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.setParameter(sortField.toString(), sortField.getID());
query.setParameter("sortField", sortField);
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
return findMany(context, query);
}

View File

@@ -0,0 +1,75 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.content.dao.impl;
import java.sql.SQLException;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.dspace.content.dao.ProcessDAO;
import org.dspace.core.AbstractHibernateDAO;
import org.dspace.core.Context;
import org.dspace.scripts.Process;
import org.dspace.scripts.Process_;
/**
* Implementation class for {@link ProcessDAO}
*/
public class ProcessDAOImpl extends AbstractHibernateDAO<Process> implements ProcessDAO {
@Override
public List<Process> findAllSortByScript(Context context) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
Root<Process> processRoot = criteriaQuery.from(Process.class);
criteriaQuery.select(processRoot);
criteriaQuery.orderBy(criteriaBuilder.asc(processRoot.get(Process_.name)));
return list(context, criteriaQuery, false, Process.class, -1, -1);
}
@Override
public List<Process> findAllSortByStartTime(Context context) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
Root<Process> processRoot = criteriaQuery.from(Process.class);
criteriaQuery.select(processRoot);
criteriaQuery.orderBy(criteriaBuilder.desc(processRoot.get(Process_.startTime)),
criteriaBuilder.desc(processRoot.get(Process_.processId)));
return list(context, criteriaQuery, false, Process.class, -1, -1);
}
@Override
public List<Process> findAll(Context context, int limit, int offset) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
Root<Process> processRoot = criteriaQuery.from(Process.class);
criteriaQuery.select(processRoot);
return list(context, criteriaQuery, false, Process.class, limit, offset);
}
@Override
public int countRows(Context context) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
Root<Process> processRoot = criteriaQuery.from(Process.class);
criteriaQuery.select(processRoot);
return count(context, criteriaQuery, criteriaBuilder, processRoot);
}
}

View File

@@ -8,6 +8,7 @@
package org.dspace.content.dao.impl;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
@@ -18,6 +19,8 @@ import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType;
import org.dspace.content.Relationship_;
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.Context;
@@ -25,6 +28,14 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
@Override
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);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
@@ -32,11 +43,25 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
criteriaQuery
.where(criteriaBuilder.or(criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), 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 findLeftPlaceByLeftItem(Context context, Item item) throws SQLException {
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
public int findNextLeftPlaceByLeftItem(Context context, Item item) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
@@ -45,39 +70,165 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
List<Relationship> list = list(context, criteriaQuery, false, Relationship.class, -1, -1);
list.sort((o1, o2) -> o2.getLeftPlace() - o1.getLeftPlace());
if (!list.isEmpty()) {
return list.get(0).getLeftPlace();
return list.get(0).getLeftPlace() + 1;
} else {
return 1;
return 0;
}
}
@Override
public int findRightPlaceByRightItem(Context context, Item item) throws SQLException {
public int findNextRightPlaceByRightItem(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.equal(relationshipRoot.get(Relationship_.rightItem), item));
List<Relationship> list = list(context, criteriaQuery, false, Relationship.class, -1, -1);
list.sort((o1, o2) -> o2.getLeftPlace() - o1.getLeftPlace());
list.sort((o1, o2) -> o2.getRightPlace() - o1.getRightPlace());
if (!list.isEmpty()) {
return list.get(0).getLeftPlace();
return list.get(0).getRightPlace() + 1;
} else {
return 1;
return 0;
}
}
@Override
public List<Relationship> findByRelationshipType(Context context, RelationshipType relationshipType)
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);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.select(relationshipRoot);
criteriaQuery
.where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType), relationshipType));
return list(context, criteriaQuery, true, Relationship.class, -1, -1);
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 {
@Override
public RelationshipType findByTypesAndLabels(Context context, EntityType leftType, EntityType rightType,
String leftLabel, String rightLabel)
public RelationshipType findbyTypesAndTypeName(Context context, EntityType leftType, EntityType rightType,
String leftwardType, String rightwardType)
throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class);
Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class);
criteriaQuery.select(relationshipTypeRoot);
criteriaQuery.where(
criteriaBuilder.and(criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftType), leftType),
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightType), rightType),
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftLabel), leftLabel),
criteriaBuilder
.equal(relationshipTypeRoot.get(RelationshipType_.rightLabel), rightLabel)));
criteriaBuilder.and(
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftType), leftType),
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightType), rightType),
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftwardType), leftwardType),
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightwardType), rightwardType)));
return uniqueResult(context, criteriaQuery, false, RelationshipType.class, -1, -1);
}
@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);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, RelationshipType.class);
Root<RelationshipType> relationshipTypeRoot = criteriaQuery.from(RelationshipType.class);
criteriaQuery.select(relationshipTypeRoot);
criteriaQuery.where(
criteriaBuilder.or(
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftLabel), label),
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.rightLabel), label)
criteriaBuilder.equal(relationshipTypeRoot.get(RelationshipType_.leftwardType), type),
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
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);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, 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)
)
);
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.InProgressSubmission;
import org.dspace.content.RelationshipMetadataService;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
@@ -112,6 +113,8 @@ public abstract class ContentServiceFactory {
*/
public abstract EntityService getEntityService();
public abstract RelationshipMetadataService getRelationshipMetadataService();
public InProgressSubmissionService getInProgressSubmissionService(InProgressSubmission inProgressSubmission) {
if (inProgressSubmission instanceof WorkspaceItem) {
return getWorkspaceItemService();

View File

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

View File

@@ -109,6 +109,31 @@ public interface BundleService extends DSpaceObjectService<Bundle>, DSpaceObject
public List<ResourcePolicy> getBundlePolicies(Context context, Bundle bundle) throws SQLException;
/**
* Moves a bitstream within a bundle from one place to another, shifting all other bitstreams in the process
*
* @param context DSpace Context
* @param bundle The bitstream bundle
* @param from The index of the bitstream to move
* @param to The index to move the bitstream to
* @throws AuthorizeException when an SQL error has occurred (querying DSpace)
* @throws SQLException If the user can't make the changes
*/
public void updateBitstreamOrder(Context context, Bundle bundle, int from, int to) throws AuthorizeException,
SQLException;
/**
* Moves a bitstream from its current bundle to a new target bundle
* @param context DSpace Context
* @param targetBundle The target bundle where bitstream will be moved to
* @param bitstream The bitstream being moved
* @throws SQLException if database error
* @throws AuthorizeException if authorization error
* @throws IOException if IO error
*/
public void moveBitstreamToBundle(Context context, Bundle targetBundle, Bitstream bitstream) throws SQLException,
AuthorizeException, IOException;
/**
* Changes bitstream order according to the array
*

View File

@@ -36,6 +36,19 @@ public interface EntityService {
*/
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.
* 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
* equal to the passed along label String
* @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
* that is equal to the label param
* @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
@@ -89,6 +116,22 @@ public interface EntityService {
*/
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
* Entity
@@ -101,6 +144,23 @@ public interface EntityService {
*/
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
* Entity
@@ -113,15 +173,46 @@ public interface EntityService {
*/
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
* label parameter that's being passed along
* @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
* to the given label parameter
* @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;
/**
* 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
* @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.MetadataField;
import org.dspace.content.MetadataValue;
import org.dspace.content.RelationshipMetadataValue;
import org.dspace.content.Thumbnail;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.virtual.VirtualMetadataPopulator;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
@@ -40,7 +38,7 @@ import org.dspace.eperson.Group;
* @author kevinvandevelde at atmire.com
*/
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;
@@ -205,7 +203,7 @@ public interface ItemService
* @throws SQLException if database error
*/
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.
@@ -677,19 +675,6 @@ public interface ItemService
*/
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.
* 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
* @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
@@ -40,6 +52,16 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
*/
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
* if this is a valid relationship
@@ -52,26 +74,26 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
public Relationship create(Context context, Relationship relationship) throws SQLException, AuthorizeException;
/**
* Retrieves the highest integer value for the leftplace property of a Relationship for all relationships
* that have the given item as a left item
* This method returns the next leftplace integer to use for a relationship with this item as the leftItem
*
* @param context The relevant DSpace context
* @param item The item that has to be the leftItem of a relationship for it to qualify
* @return The integer value of the highest left place property of all relationships
* that have the given item as a leftitem property
* @return The next integer to be used for the leftplace of a relationship with the given item
* as a left item
* @throws SQLException If something goes wrong
*/
int findLeftPlaceByLeftItem(Context context, Item item) throws SQLException;
int findNextLeftPlaceByLeftItem(Context context, Item item) throws SQLException;
/**
* Retrieves the highest integer value for the rightplace property of a Relationship for all relationships
* that have the given item as a right item
* This method returns the next rightplace integer to use for a relationship with this item as the rightItem
*
* @param context The relevant DSpace context
* @param item The item that has to be the rightitem of a relationship for it to qualify
* @return The integer value of the highest right place property of all relationships
* that have the given item as a rightitem property
* @return The next integer to be used for the rightplace of a relationship with the given item
* as a right item
* @throws SQLException If something goes wrong
*/
int findRightPlaceByRightItem(Context context, Item item) throws SQLException;
int findNextRightPlaceByRightItem(Context context, Item item) throws SQLException;
/**
* This method returns a list of Relationships for which the leftItem or rightItem is equal to the given
@@ -87,18 +109,47 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
RelationshipType relationshipType)
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
* 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
* by the leftItem, rightItem and relationshipType of the given Relationship.
* @param context The relevant DSpace context
* @param relationship The Relationship object that will have it's place updated and that will be used
* to retrieve the other relationships whose place might need to be updated
* @param isCreation Is the relationship new or did it already exist
* @throws SQLException If something goes wrong
*/
public void updatePlaceInRelationship(Context context, Relationship relationship, boolean isCreation)
public void updatePlaceInRelationship(Context context, Relationship relationship)
throws SQLException, AuthorizeException;
/**
@@ -116,7 +167,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
* @param context The relevant DSpace context
* @param relationshipType The RelationshipType object that will be used to check the Relationship on
@@ -126,6 +177,20 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
*/
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
* @param c The relevant DSpace context
@@ -134,6 +199,26 @@ public interface RelationshipService extends DSpaceCRUDService<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
* @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
* @throws AuthorizeException If something goes wrong
* @throws SQLException If something goes wrong
@@ -141,4 +226,82 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
Relationship create(Context c, Item leftItem, Item rightItem, RelationshipType relationshipType,
int leftPlace, int rightPlace)
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 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
* @param context The relevant DSpace context
* @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 leftLabel The leftLabel String that needs to match for the returned RelationshipType
* @param rightLabel The rightLabel String that needs to match for the returned RelationshipType
* @param leftwardType The leftwardType String that needs to match for the returned RelationshipType
* @param rightwardType The rightwardType String that needs to match for the returned RelationshipType
* @return
* @throws SQLException If something goes wrong
*/
RelationshipType findbyTypesAndLabels(Context context,EntityType leftType,EntityType rightType,
String leftLabel,String rightLabel)
RelationshipType findbyTypesAndTypeName(Context context, EntityType leftType, EntityType rightType,
String leftwardType, String rightwardType)
throws SQLException;
/**
@@ -54,15 +54,40 @@ public interface RelationshipTypeService extends DSpaceCRUDService<RelationshipT
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
* @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
* that is equal to the given label param
* @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
@@ -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, 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
* @param context The relevant DSpace context
* @param leftEntityType The leftEntityType EntityType object for this relationshipType
* @param rightEntityType The rightEntityType EntityType object for this relationshipType
* @param leftLabel The leftLabel String object for this relationshipType
* @param rightLabel The rightLabel String object for this relationshipType
* @param leftwardType The leftwardType String object for this relationshipType
* @param rightwardType The rightwardType String object for this relationshipType
* @param leftCardinalityMinInteger The leftCardinalityMinInteger Integer object for this relationshipType
* @param leftCardinalityMaxInteger The leftCardinalityMaxInteger 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 AuthorizeException If something goes wrong
*/
RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType, String leftLabel,
String rightLabel, Integer leftCardinalityMinInteger, Integer leftCardinalityMaxInteger,
Integer rightCardinalityMinInteger, Integer rightCardinalityMaxInteger)
RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType,
String leftwardType, String rightwardType, Integer leftCardinalityMinInteger,
Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger,
Integer rightCardinalityMaxInteger)
throws SQLException, AuthorizeException;
}

View File

@@ -65,6 +65,7 @@ public class Collected implements VirtualMetadataConfiguration {
* Generic setter for the useForPlace property
* @param useForPlace The boolean value that the useForPlace property will be set to
*/
@Override
public void setUseForPlace(boolean useForPlace) {
this.useForPlace = useForPlace;
}
@@ -73,10 +74,19 @@ public class Collected implements VirtualMetadataConfiguration {
* Generic getter for the useForPlace property
* @return The useForPlace to be used by this bean
*/
@Override
public boolean getUseForPlace() {
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
* 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 populateWithNameVariant = false;
/**
* Generic getter for the fields property
* @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
* @param useForPlace The boolean value that the useForPlace property will be set to
*/
@Override
public void setUseForPlace(boolean useForPlace) {
this.useForPlace = useForPlace;
}
@@ -88,10 +90,21 @@ public class Concatenate implements VirtualMetadataConfiguration {
* Generic getter for the useForPlace property
* @return The useForPlace to be used by this bean
*/
@Override
public boolean getUseForPlace() {
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
* 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
* @return The String value for all of the retrieved metadatavalues combined with the separator
*/
@Override
public List<String> getValues(Context context, Item item) {
List<String> resultValues = new LinkedList<>();

View File

@@ -120,6 +120,7 @@ public class Related implements VirtualMetadataConfiguration {
* Generic setter for the useForPlace property
* @param useForPlace The boolean value that the useForPlace property will be set to
*/
@Override
public void setUseForPlace(boolean useForPlace) {
this.useForPlace = useForPlace;
}
@@ -128,10 +129,19 @@ public class Related implements VirtualMetadataConfiguration {
* Generic getter for the useForPlace property
* @return The useForPlace to be used by this bean
*/
@Override
public boolean getUseForPlace() {
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
* 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
* @throws SQLException If something goes wrong
*/
@Override
public List<String> getValues(Context context, Item item) throws SQLException {
Entity entity = entityService.findByItemId(context, item.getID());
EntityType entityType = entityService.getType(context, entity);
@@ -149,8 +160,8 @@ public class Related implements VirtualMetadataConfiguration {
List<RelationshipType> relationshipTypes = entityService.getAllRelationshipTypes(context, entity);
List<RelationshipType> possibleRelationshipTypes = new LinkedList<>();
for (RelationshipType relationshipType : relationshipTypes) {
if (StringUtils.equals(relationshipType.getLeftLabel(), relationshipTypeString) || StringUtils
.equals(relationshipType.getRightLabel(), relationshipTypeString)) {
if (StringUtils.equals(relationshipType.getLeftwardType(), relationshipTypeString) || StringUtils
.equals(relationshipType.getRightwardType(), relationshipTypeString)) {
possibleRelationshipTypes.add(relationshipType);
}
}

View File

@@ -38,4 +38,12 @@ public class UUIDValue implements VirtualMetadataConfiguration {
public boolean getUseForPlace() {
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
*/
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
* 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 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
*/
public boolean isUseForPlaceTrueForRelationshipType(RelationshipType relationshipType, boolean isLeft) {
HashMap<String, VirtualMetadataConfiguration> hashMaps;
if (isLeft) {
hashMaps = this.getMap().get(relationshipType.getLeftLabel());
hashMaps = this.getMap().get(relationshipType.getLeftwardType());
} else {
hashMaps = this.getMap().get(relationshipType.getRightLabel());
hashMaps = this.getMap().get(relationshipType.getRightwardType());
}
if (hashMaps != null) {
for (Map.Entry<String, VirtualMetadataConfiguration> entry : hashMaps.entrySet()) {

View File

@@ -66,10 +66,16 @@ public abstract class AbstractHibernateDAO<T> implements GenericDAO<T> {
@Override
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);
Root<T> root = criteriaQuery.from(clazz);
criteriaQuery.select(root);
return executeCriteriaQuery(context, criteriaQuery, false, -1, -1);
return executeCriteriaQuery(context, criteriaQuery, false, limit, offset);
}
@Override

View File

@@ -58,6 +58,18 @@ public interface GenericDAO<T> {
*/
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.
*

View File

@@ -360,6 +360,11 @@ public class LegacyPluginServiceImpl implements PluginService {
return null;
}
@Override
public void clearNamedPluginClasses() {
namedPluginClasses.clear();
}
/**
* Returns whether a plugin exists which implements the specified interface
* 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
*/
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

@@ -13,11 +13,8 @@ import java.util.Iterator;
import java.util.UUID;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.logging.log4j.Logger;
import org.apache.commons.cli.ParseException;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.Item;
@@ -26,103 +23,26 @@ import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.handle.factory.HandleServiceFactory;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.scripts.DSpaceRunnable;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Class used to reindex dspace communities/collections/items into discovery
*
* @author Kevin Van de Velde (kevin at atmire dot com)
* @author Mark Diggory (markd at atmire dot com)
* @author Ben Bosman (ben at atmire dot com)
*/
public class IndexClient {
public class IndexClient extends DSpaceRunnable {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(IndexClient.class);
private Context context;
/**
* Default constructor
*/
private IndexClient() { }
@Autowired
private IndexingService indexer;
/**
* When invoked as a command-line tool, creates, updates, removes content
* from the whole index
*
* @param args the command-line arguments, none used
* @throws SQLException An exception that provides information on a database access error or other errors.
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
* @throws SearchServiceException if something went wrong with querying the solr server
*/
public static void main(String[] args) throws SQLException, IOException, SearchServiceException {
private IndexClientOptions indexClientOptions;
Context context = new Context(Context.Mode.READ_ONLY);
context.turnOffAuthorisationSystem();
String usage = "org.dspace.discovery.IndexClient [-cbhf] | [-r <handle>] | [-i <handle>] or nothing to " +
"update/clean an existing index.";
Options options = new Options();
HelpFormatter formatter = new HelpFormatter();
CommandLine line = null;
options.addOption(OptionBuilder
.withArgName("handle to remove")
.hasArg(true)
.withDescription(
"remove an Item, Collection or Community from index based on its handle")
.create("r"));
options.addOption(OptionBuilder
.withArgName("handle or uuid to add or update")
.hasArg(true)
.withDescription(
"add or update an Item, Collection or Community based on its handle or uuid")
.create("i"));
options.addOption(OptionBuilder
.isRequired(false)
.withDescription(
"clean existing index removing any documents that no longer exist in the db")
.create("c"));
options.addOption(OptionBuilder
.isRequired(false)
.withDescription(
"(re)build index, wiping out current one if it exists")
.create("b"));
options.addOption(OptionBuilder
.isRequired(false)
.withDescription(
"Rebuild the spellchecker, can be combined with -b and -f.")
.create("s"));
options.addOption(OptionBuilder
.isRequired(false)
.withDescription(
"if updating existing index, force each handle to be reindexed even if uptodate")
.create("f"));
options.addOption(OptionBuilder
.isRequired(false)
.withDescription(
"print this help message")
.create("h"));
options.addOption(OptionBuilder.isRequired(false).withDescription(
"optimize search core").create("o"));
try {
line = new PosixParser().parse(options, args);
} catch (Exception e) {
// automatically generate the help statement
formatter.printHelp(usage, e.getMessage(), options, "");
System.exit(1);
}
if (line.hasOption("h")) {
// automatically generate the help statement
formatter.printHelp(usage, options);
System.exit(1);
@Override
public void internalRun() throws Exception {
if (indexClientOptions == IndexClientOptions.HELP) {
printHelp();
return;
}
/** Acquire from dspace-services in future */
@@ -130,28 +50,29 @@ public class IndexClient {
* new DSpace.getServiceManager().getServiceByName("org.dspace.discovery.SolrIndexer");
*/
IndexingService indexer = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
IndexingService.class.getName(),
IndexingService.class
);
if (line.hasOption("r")) {
log.info("Removing " + line.getOptionValue("r") + " from Index");
indexer.unIndexContent(context, line.getOptionValue("r"));
} else if (line.hasOption("c")) {
log.info("Cleaning Index");
indexer.cleanIndex(line.hasOption("f"));
} else if (line.hasOption("b")) {
log.info("(Re)building index from scratch.");
if (indexClientOptions == IndexClientOptions.REMOVE) {
handler.logInfo("Removing " + commandLine.getOptionValue("r") + " from Index");
indexer.unIndexContent(context, commandLine.getOptionValue("r"));
} else if (indexClientOptions == IndexClientOptions.CLEAN) {
handler.logInfo("Cleaning Index");
indexer.cleanIndex(false);
} else if (indexClientOptions == IndexClientOptions.FORCECLEAN) {
handler.logInfo("Cleaning Index");
indexer.cleanIndex(true);
} else if (indexClientOptions == IndexClientOptions.BUILD ||
indexClientOptions == IndexClientOptions.BUILDANDSPELLCHECK) {
handler.logInfo("(Re)building index from scratch.");
indexer.createIndex(context);
checkRebuildSpellCheck(line, indexer);
} else if (line.hasOption("o")) {
log.info("Optimizing search core.");
if (indexClientOptions == IndexClientOptions.BUILDANDSPELLCHECK) {
checkRebuildSpellCheck(commandLine, indexer);
}
} else if (indexClientOptions == IndexClientOptions.OPTIMIZE) {
handler.logInfo("Optimizing search core.");
indexer.optimize();
} else if (line.hasOption('s')) {
checkRebuildSpellCheck(line, indexer);
} else if (line.hasOption('i')) {
final String param = line.getOptionValue('i');
} else if (indexClientOptions == IndexClientOptions.SPELLCHECK) {
checkRebuildSpellCheck(commandLine, indexer);
} else if (indexClientOptions == IndexClientOptions.INDEX) {
final String param = commandLine.getOptionValue('i');
UUID uuid = null;
try {
uuid = UUID.fromString(param);
@@ -171,24 +92,55 @@ public class IndexClient {
}
} else {
dso = (IndexableObject) HandleServiceFactory.getInstance()
.getHandleService().resolveToObject(context, param);
.getHandleService().resolveToObject(context, param);
}
if (dso == null) {
throw new IllegalArgumentException("Cannot resolve " + param + " to a DSpace object");
}
log.info("Indexing " + param + " force " + line.hasOption("f"));
handler.logInfo("Indexing " + param + " force " + commandLine.hasOption("f"));
final long startTimeMillis = System.currentTimeMillis();
final long count = indexAll(indexer, ContentServiceFactory.getInstance().getItemService(), context, dso);
final long count = indexAll(indexer, ContentServiceFactory.getInstance().getItemService(), context,
dso);
final long seconds = (System.currentTimeMillis() - startTimeMillis) / 1000;
log.info("Indexed " + count + " object" + (count > 1 ? "s" : "") + " in " + seconds + " seconds");
} else {
log.info("Updating and Cleaning Index");
indexer.cleanIndex(line.hasOption("f"));
indexer.updateIndex(context, line.hasOption("f"));
checkRebuildSpellCheck(line, indexer);
handler.logInfo("Indexed " + count + " object" + (count > 1 ? "s" : "") + " in " + seconds + " seconds");
} else if (indexClientOptions == IndexClientOptions.UPDATE ||
indexClientOptions == IndexClientOptions.UPDATEANDSPELLCHECK) {
handler.logInfo("Updating and Cleaning Index");
indexer.cleanIndex(false);
indexer.updateIndex(context, false);
if (indexClientOptions == IndexClientOptions.UPDATEANDSPELLCHECK) {
checkRebuildSpellCheck(commandLine, indexer);
}
} else if (indexClientOptions == IndexClientOptions.FORCEUPDATE ||
indexClientOptions == IndexClientOptions.FORCEUPDATEANDSPELLCHECK) {
handler.logInfo("Updating and Cleaning Index");
indexer.cleanIndex(true);
indexer.updateIndex(context, true);
if (indexClientOptions == IndexClientOptions.FORCEUPDATEANDSPELLCHECK) {
checkRebuildSpellCheck(commandLine, indexer);
}
}
log.info("Done with indexing");
handler.logInfo("Done with indexing");
}
public void setup() throws ParseException {
try {
context = new Context(Context.Mode.READ_ONLY);
context.turnOffAuthorisationSystem();
} catch (Exception e) {
throw new ParseException("Unable to create a new DSpace Context: " + e.getMessage());
}
indexClientOptions = IndexClientOptions.getIndexClientOption(commandLine);
}
/**
* Constructor for this class. This will ensure that the Options are created and set appropriately.
*/
private IndexClient() {
Options options = IndexClientOptions.constructOptions();
this.options = options;
}
/**
@@ -273,13 +225,12 @@ public class IndexClient {
* @param line the command line options
* @param indexer the solr indexer
* @throws SearchServiceException in case of a solr exception
* @throws java.io.IOException passed through
* @throws IOException passed through
*/
protected static void checkRebuildSpellCheck(CommandLine line, IndexingService indexer)
protected void checkRebuildSpellCheck(CommandLine line, IndexingService indexer)
throws SearchServiceException, IOException {
if (line.hasOption("s")) {
log.info("Rebuilding spell checker.");
indexer.buildSpellCheck();
}
handler.logInfo("Rebuilding spell checker.");
indexer.buildSpellCheck();
}
}

View File

@@ -0,0 +1,97 @@
/**
* 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.discovery;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
/**
* This Enum holds all the possible options and combinations for the Index discovery script
*/
public enum IndexClientOptions {
REMOVE,
CLEAN,
FORCECLEAN,
BUILD,
BUILDANDSPELLCHECK,
OPTIMIZE,
SPELLCHECK,
INDEX,
UPDATE,
FORCEUPDATE,
UPDATEANDSPELLCHECK,
FORCEUPDATEANDSPELLCHECK,
HELP;
/**
* This method resolves the CommandLine parameters to figure out which action the index-discovery script should
* perform
* @param commandLine The relevant CommandLine for the index-discovery script
* @return The index-discovery option to be ran, parsed from the CommandLine
*/
protected static IndexClientOptions getIndexClientOption(CommandLine commandLine) {
if (commandLine.hasOption("h")) {
return IndexClientOptions.HELP;
} else if (commandLine.hasOption("r")) {
return IndexClientOptions.REMOVE;
} else if (commandLine.hasOption("c")) {
if (commandLine.hasOption("f")) {
return IndexClientOptions.FORCECLEAN;
} else {
return IndexClientOptions.CLEAN;
}
} else if (commandLine.hasOption("b")) {
if (commandLine.hasOption("s")) {
return IndexClientOptions.BUILDANDSPELLCHECK;
} else {
return IndexClientOptions.BUILD;
}
} else if (commandLine.hasOption("o")) {
return IndexClientOptions.OPTIMIZE;
} else if (commandLine.hasOption("s")) {
return IndexClientOptions.SPELLCHECK;
} else if (commandLine.hasOption("i")) {
return IndexClientOptions.INDEX;
} else {
if (commandLine.hasOption("f") && commandLine.hasOption("s")) {
return IndexClientOptions.FORCEUPDATEANDSPELLCHECK;
} else if (commandLine.hasOption("f")) {
return IndexClientOptions.FORCEUPDATE;
} else if (commandLine.hasOption("s")) {
return IndexClientOptions.UPDATEANDSPELLCHECK;
} else {
return IndexClientOptions.UPDATE;
}
}
}
protected static Options constructOptions() {
Options options = new Options();
options
.addOption("r", "remove", true, "remove an Item, Collection or Community from index based on its handle");
options.getOption("r").setType(String.class);
options.addOption("i", "index", true,
"add or update an Item, Collection or Community based on its handle or uuid");
options.getOption("i").setType(boolean.class);
options.addOption("c", "clean", false,
"clean existing index removing any documents that no longer exist in the db");
options.getOption("c").setType(boolean.class);
options.addOption("b", "build", false, "(re)build index, wiping out current one if it exists");
options.getOption("b").setType(boolean.class);
options.addOption("s", "spellchecker", false, "Rebuild the spellchecker, can be combined with -b and -f.");
options.getOption("s").setType(boolean.class);
options.addOption("f", "force", false,
"if updating existing index, force each handle to be reindexed even if uptodate");
options.getOption("f").setType(boolean.class);
options.addOption("h", "help", false, "print this help message");
options.getOption("h").setType(boolean.class);
return options;
}
}

View File

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

View File

@@ -51,6 +51,22 @@ public class DiscoveryConfiguration implements InitializingBean {
private DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration;
private DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration;
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() {
return id;

View File

@@ -7,6 +7,7 @@
*/
package org.dspace.discovery.configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
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) {
System.out.println(DSpaceServicesFactory.getInstance().getServiceManager().getServicesNames().size());
DiscoveryConfigurationService mainService = DSpaceServicesFactory.getInstance().getServiceManager()

View File

@@ -13,11 +13,11 @@ import java.sql.SQLException;
import java.util.Iterator;
import org.apache.logging.log4j.Logger;
import org.dspace.app.launcher.ScriptLauncher;
import org.dspace.content.MetadataValue;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.MetadataValueService;
import org.dspace.core.Context;
import org.dspace.discovery.IndexClient;
import org.dspace.handle.factory.HandleServiceFactory;
import org.dspace.handle.service.HandleService;
import org.dspace.services.ConfigurationService;
@@ -139,7 +139,7 @@ public class UpdateHandlePrefix {
try {
// Reinitialise the search and browse system
IndexClient.main(new String[] {"-b"});
ScriptLauncher.main(new String[] {"index-discovery", "-b"});
System.out.println("Browse and search indexes are ready now.");
// All done
System.out.println("\nAll done successfully. Please check the DSpace logs!\n");

View File

@@ -7,16 +7,28 @@
*/
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.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
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.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.harvest.dao.HarvestedCollectionDAO;
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;
/**
@@ -27,6 +39,10 @@ import org.springframework.beans.factory.annotation.Autowired;
* @author kevinvandevelde at atmire.com
*/
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)
protected HarvestedCollectionDAO harvestedCollectionDAO;
@@ -156,5 +172,94 @@ public class HarvestedCollectionServiceImpl implements HarvestedCollectionServic
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.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
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.Identify;
import ORG.oclc.oai.harvester2.verb.ListIdentifiers;
import ORG.oclc.oai.harvester2.verb.ListMetadataFormats;
import ORG.oclc.oai.harvester2.verb.ListRecords;
import org.apache.commons.lang3.StringUtils;
@@ -102,7 +105,7 @@ public class OAIHarvester {
protected BitstreamFormatService bitstreamFormatService;
protected BundleService bundleService;
protected CollectionService collectionService;
protected HarvestedCollectionService harvestedCollection;
protected HarvestedCollectionService harvestedCollectionService;
protected InstallItemService installItemService;
protected ItemService itemService;
protected HandleService handleService;
@@ -140,7 +143,7 @@ public class OAIHarvester {
bundleService = ContentServiceFactory.getInstance().getBundleService();
collectionService = ContentServiceFactory.getInstance().getCollectionService();
handleService = HandleServiceFactory.getInstance().getHandleService();
harvestedCollection = HarvestServiceFactory.getInstance().getHarvestedCollectionService();
harvestedCollectionService = HarvestServiceFactory.getInstance().getHarvestedCollectionService();
harvestedItemService = HarvestServiceFactory.getInstance().getHarvestedItemService();
itemService = ContentServiceFactory.getInstance().getItemService();
installItemService = ContentServiceFactory.getInstance().getInstallItemService();
@@ -150,7 +153,6 @@ public class OAIHarvester {
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
if (dso.getType() != Constants.COLLECTION) {
throw new HarvestingException("OAIHarvester can only harvest collections");
}
@@ -159,7 +161,7 @@ public class OAIHarvester {
targetCollection = (Collection) dso;
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");
}
@@ -188,7 +190,7 @@ public class OAIHarvester {
*
* @return Namespace of the supported ORE format. Returns null if not found.
*/
private static Namespace getORENamespace() {
public static Namespace getORENamespace() {
String ORESerializationString = null;
String ORESeialKey = null;
String oreString = "oai.harvester.oreSerializationFormat";
@@ -213,7 +215,7 @@ public class OAIHarvester {
* @param metadataKey
* @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 metaString = "oai.harvester.metadataformats";
@@ -313,7 +315,7 @@ public class OAIHarvester {
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_BUSY);
harvestRow.setHarvestMessage("Collection harvesting is initializing...");
harvestRow.setHarvestStartTime(startTime);
harvestedCollection.update(ourContext, harvestRow);
harvestedCollectionService.update(ourContext, harvestRow);
intermediateCommit();
// expiration timer starts
@@ -354,7 +356,7 @@ public class OAIHarvester {
harvestRow.setHarvestStartTime(new Date());
harvestRow.setHarvestMessage("OAI server did not contain any updates");
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_READY);
harvestedCollection.update(ourContext, harvestRow);
harvestedCollectionService.update(ourContext, harvestRow);
return;
} else {
throw new HarvestingException(errorSet.toString());
@@ -411,7 +413,7 @@ public class OAIHarvester {
harvestRow.setHarvestMessage(String
.format("Collection is currently being harvested (item %d of %d)",
currentRecord, totalListSize));
harvestedCollection.update(ourContext, harvestRow);
harvestedCollectionService.update(ourContext, harvestRow);
} finally {
//In case of an exception, make sure to restore our authentication state to the previous state
ourContext.restoreAuthSystemState();
@@ -429,19 +431,19 @@ public class OAIHarvester {
alertAdmin(HarvestedCollection.STATUS_OAI_ERROR, hex);
}
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_OAI_ERROR);
harvestedCollection.update(ourContext, harvestRow);
harvestedCollectionService.update(ourContext, harvestRow);
ourContext.complete();
return;
} catch (Exception ex) {
harvestRow.setHarvestMessage("Unknown error occurred while generating an OAI response");
harvestRow.setHarvestStatus(HarvestedCollection.STATUS_UNKNOWN_ERROR);
harvestedCollection.update(ourContext, harvestRow);
harvestedCollectionService.update(ourContext, harvestRow);
alertAdmin(HarvestedCollection.STATUS_UNKNOWN_ERROR, ex);
log.error("Error occurred while generating an OAI response: " + ex.getMessage() + " " + ex.getCause(), ex);
ourContext.complete();
return;
} finally {
harvestedCollection.update(ourContext, harvestRow);
harvestedCollectionService.update(ourContext, harvestRow);
ourContext.turnOffAuthorisationSystem();
collectionService.update(ourContext, targetCollection);
ourContext.restoreAuthSystemState();
@@ -456,7 +458,7 @@ public class OAIHarvester {
log.info(
"Harvest from " + oaiSource + " successful. The process took " + timeTaken + " milliseconds. Harvested "
+ currentRecord + " items.");
harvestedCollection.update(ourContext, harvestRow);
harvestedCollectionService.update(ourContext, harvestRow);
ourContext.setMode(originalMode);
}
@@ -900,94 +902,44 @@ public class OAIHarvester {
String oaiSetId = harvestRow.getOaiSetId();
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
* supporting the provided metadata formats.
* Return all available 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.
* @return a list containing a map for each supported metadata format
*/
public static List<String> verifyOAIharvester(String oaiSource,
String oaiSetId, String metaPrefix, boolean testORE) {
List<String> errorSet = new ArrayList<String>();
public static List<Map<String,String>> getAvailableMetadataFormats() {
List<Map<String,String>> configs = new ArrayList<>();
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.
try {
new Identify(oaiSource);
} catch (Exception ex) {
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached.");
return errorSet;
}
String id = key.substring(metaString.length());
String label;
String namespace = "";
// 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, 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");
}
}
if (metadataString.indexOf(',') != -1) {
label = metadataString.substring(metadataString.indexOf(',') + 2);
namespace = metadataString.substring(0, metadataString.indexOf(','));
} else {
label = id + "(" + metadataString + ")";
}
} catch (RuntimeException re) {
throw re;
} catch (Exception e) {
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached");
return errorSet;
Map<String,String> config = new HashMap<>();
config.put("id", id);
config.put("label", label);
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 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,108 @@
/**
* 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.scripts;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
/**
* This class serves as a representation of a command line parameter by holding a String name and a String value
*/
public class DSpaceCommandLineParameter {
private String name;
private String value;
public static String SEPARATOR = "|||";
/**
* This constructor will take a String key and String value and store them in their appriopriate fields
* @param key The String value to be stored as the name of the parameter
* @param value The String value to be stored as the value of the parameter
*/
public DSpaceCommandLineParameter(String key, String value) {
this.name = key;
if (StringUtils.isBlank(value)) {
this.value = null;
} else {
this.value = value;
}
}
/**
* This constructors accepts a single parameter String that is defined as e.g. "-c test" and it'll parse this
* String into the key "-c" and value "test" to then call the other constructor with those parameters
* @param parameter The String parameter
*/
protected DSpaceCommandLineParameter(String parameter) {
this(StringUtils.substringBefore(parameter, " "), StringUtils.substringAfter(parameter, " "));
}
public String getName() {
return name;
}
public void setName(String key) {
this.name = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
/**
* Converts the DSpaceCommandLineParameter into a String format by concatenating the value and the name String
* values by separating them with a space
* @return The String representation of a DSpaceCommandlineParameter object
*/
public String toString() {
String stringToReturn = "";
stringToReturn += getName();
if (StringUtils.isNotBlank(getValue())) {
stringToReturn += " ";
stringToReturn += getValue();
}
return stringToReturn;
}
/**
* This method will convert a list of DSpaceCommandLineParameter objects into a single String. This is done by
* calling the toString() method on each of the DSpaceCommandLineParameter objects in the list and concatenating
* them with the Separator defined in this class
* @param parameterList The list of DSpaceCommandLineParameter objects to be converted into a String
* @return The resulting String
*/
public static String concatenate(List<DSpaceCommandLineParameter> parameterList) {
if (parameterList.isEmpty()) {
return null;
}
return parameterList.stream().map(parameter -> parameter.toString()).collect(Collectors.joining(SEPARATOR));
}
/**
* Will return a boolean indicating whether the given param is equal to this object
* @param other The other object
* @return A boolean indicating equality
*/
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (other.getClass() != DSpaceCommandLineParameter.class) {
return false;
}
return StringUtils.equals(this.getName(), ((DSpaceCommandLineParameter) other).getName()) && StringUtils
.equals(this.getValue(), ((DSpaceCommandLineParameter) other).getValue());
}
}

View File

@@ -0,0 +1,156 @@
/**
* 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.scripts;
import java.sql.SQLException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Context;
import org.dspace.scripts.handler.DSpaceRunnableHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
/**
* This abstract class is the class that should be extended by each script.
* it provides the basic variables to be hold by the script as well as the means to initialize, parse and run the script
* Every DSpaceRunnable that is implemented in this way should be defined in the scripts.xml config file as a bean
*/
public abstract class DSpaceRunnable implements Runnable {
/**
* The name of the script
*/
private String name;
/**
* The description of the script
*/
private String description;
/**
* The CommandLine object for the script that'll hold the information
*/
protected CommandLine commandLine;
/**
* The possible options for this script
*/
protected Options options;
/**
* The handler that deals with this script. This handler can currently either be a RestDSpaceRunnableHandler or
* a CommandlineDSpaceRunnableHandler depending from where the script is called
*/
protected DSpaceRunnableHandler handler;
@Autowired
private AuthorizeService authorizeService;
public String getName() {
return name;
}
@Required
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
@Required
public void setDescription(String description) {
this.description = description;
}
public Options getOptions() {
return options;
}
/**
* This method will take the primitive array of String objects that represent the parameters given to the String
* and it'll parse these into a CommandLine object that can be used by the script to retrieve the data
* @param args The primitive array of Strings representing the parameters
* @throws ParseException If something goes wrong
*/
private void parse(String[] args) throws ParseException {
commandLine = new DefaultParser().parse(getOptions(), args);
setup();
}
/**
* This method will call upon the {@link DSpaceRunnableHandler#printHelp(Options, String)} method with the script's
* options and name
*/
public void printHelp() {
handler.printHelp(options, name);
}
/**
* This is the run() method from the Runnable interface that we implement. This method will handle the running
* of the script and all the database modifications needed for the Process object that resulted from this script
*/
@Override
public void run() {
try {
handler.start();
internalRun();
handler.handleCompletion();
} catch (Exception e) {
handler.handleException(e);
}
}
private void setHandler(DSpaceRunnableHandler dSpaceRunnableHandler) {
this.handler = dSpaceRunnableHandler;
}
/**
* This method sets the appropriate DSpaceRunnableHandler depending on where it was ran from and it parses
* the arguments given to the script
* @param args The arguments given to the script
* @param dSpaceRunnableHandler The DSpaceRunnableHandler object that defines from where the script was ran
* @throws ParseException If something goes wrong
*/
public void initialize(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler) throws ParseException {
this.setHandler(dSpaceRunnableHandler);
this.parse(args);
}
/**
* This method has to be included in every script and this will be the main execution block for the script that'll
* contain all the logic needed
* @throws Exception If something goes wrong
*/
public abstract void internalRun() throws Exception;
/**
* This method has to be included in every script and handles the setup of the script by parsing the CommandLine
* and setting the variables
* @throws ParseException If something goes wrong
*/
public abstract void setup() throws ParseException;
/**
* This method will return if the script is allowed to execute in the given context. This is by default set
* to the currentUser in the context being an admin, however this can be overwritten by each script individually
* if different rules apply
* @param context The relevant DSpace context
* @return A boolean indicating whether the script is allowed to execute or not
*/
public boolean isAllowedToExecute(Context context) {
try {
return authorizeService.isAdmin(context);
} catch (SQLException e) {
handler.logError("Error occured when trying to verify permissions for script: " + name);
}
return false;
}
}

View File

@@ -0,0 +1,242 @@
/**
* 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.scripts;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.dspace.content.Bitstream;
import org.dspace.content.ProcessStatus;
import org.dspace.core.ReloadableEntity;
import org.dspace.eperson.EPerson;
/**
* This class is the DB Entity representation of the Process object to be stored in the Database
*/
@Entity
@Table(name = "process")
public class Process implements ReloadableEntity<Integer> {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "process_id_seq")
@SequenceGenerator(name = "process_id_seq", sequenceName = "process_id_seq", allocationSize = 1)
@Column(name = "process_id", unique = true, nullable = false)
private Integer processId;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private EPerson ePerson;
@Column(name = "start_time")
@Temporal(TemporalType.TIMESTAMP)
private Date startTime;
@Column(name = "finished_time")
@Temporal(TemporalType.TIMESTAMP)
private Date finishedTime;
@Column(name = "script", nullable = false)
private String name;
@Column(name = "status")
@Enumerated(EnumType.STRING)
private ProcessStatus processStatus;
@Column(name = "parameters")
private String parameters;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "process2bitstream",
joinColumns = {@JoinColumn(name = "process_id")},
inverseJoinColumns = {@JoinColumn(name = "bitstream_id")}
)
private List<Bitstream> bitstreams;
@Column(name = "creation_time", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date creationTime;
protected Process() {
}
/**
* This method returns the ID that the Process holds within the Database
* @return The ID that the process holds within the database
*/
public Integer getID() {
return processId;
}
public void setProcessId(Integer processId) {
this.processId = processId;
}
/**
* This method returns an EPerson object. This EPerson object is the EPerson that initially created the process
* @return The EPerson that created the process
*/
public EPerson getEPerson() {
return ePerson;
}
public void setEPerson(EPerson ePerson) {
this.ePerson = ePerson;
}
/**
* This method returns the Start time for the Process. This reflects the time when the Process was actually started
* @return The start time for the Process
*/
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
/**
* This method returns the time that Process was finished
* @return The finished time for the Process
*/
public Date getFinishedTime() {
return finishedTime;
}
public void setFinishedTime(Date finishedTime) {
this.finishedTime = finishedTime;
}
/**
* This method returns the name of the Process. For example filter-media
* @return The name of the Process
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* This method returns a ProcessStatus value that represents the current state of the Process. These values
* can be found within the {@link ProcessStatus} enum
* @return The status of the Process
*/
public ProcessStatus getProcessStatus() {
return processStatus;
}
public void setProcessStatus(ProcessStatus processStatus) {
this.processStatus = processStatus;
}
/**
* To get the parameters, use ProcessService.getParameters() to get a parsed list of DSpaceCommandLineParameters
* This String representation is the parameter in an unparsed fashion. For example "-c test"
*/
protected String getParameters() {
return parameters;
}
public void setParameters(String parameters) {
this.parameters = parameters;
}
/**
* This method returns a list of Bitstreams that will be used or created by the Process. This list contains both
* input and output bitstreams.
* @return The Bitstreams that are used or created by the process
*/
public List<Bitstream> getBitstreams() {
return bitstreams;
}
public void setBitstreams(List<Bitstream> bitstreams) {
this.bitstreams = bitstreams;
}
public void removeBitstream(Bitstream bitstream) {
getBitstreams().remove(bitstream);
}
public void addBitstream(Bitstream bitstream) {
getBitstreams().add(bitstream);
}
public void setCreationTime(Date creationTime) {
this.creationTime = creationTime;
}
/**
* This method will return the time when the Process was created. Note that this is potentially different from
* the StartTime (for example if the Process was queued)
* @return The creation time of the Process
*/
public Date getCreationTime() {
return creationTime;
}
/**
* Return <code>true</code> if <code>other</code> is the same Process
* as this object, <code>false</code> otherwise
*
* @param other object to compare to
* @return <code>true</code> if object passed in represents the same
* collection as this object
*/
@Override
public boolean equals(Object other) {
return (other instanceof Process &&
new EqualsBuilder().append(this.getID(), ((Process) other).getID())
.append(this.getName(), ((Process) other).getName())
.append(this.getBitstreams(), ((Process) other).getBitstreams())
.append(this.getProcessStatus(), ((Process) other).getProcessStatus())
.append(this.getFinishedTime(), ((Process) other).getFinishedTime())
.append(this.getStartTime(), ((Process) other).getStartTime())
.append(this.getParameters(), ((Process) other).getParameters())
.append(this.getCreationTime(), ((Process) other).getCreationTime())
.append(this.getEPerson(), ((Process) other).getEPerson())
.isEquals());
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(this.getID())
.append(this.getName())
.append(this.getBitstreams())
.append(this.getProcessStatus())
.append(this.getFinishedTime())
.append(this.getStartTime())
.append(this.getParameters())
.append(this.getCreationTime())
.append(this.getEPerson())
.toHashCode();
}
}

View File

@@ -0,0 +1,148 @@
/**
* 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.scripts;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.content.ProcessStatus;
import org.dspace.content.dao.ProcessDAO;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
import org.dspace.scripts.service.ProcessService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* The implementation for the {@link ProcessService} class
*/
public class ProcessServiceImpl implements ProcessService {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ProcessService.class);
@Autowired
private ProcessDAO processDAO;
@Override
public Process create(Context context, EPerson ePerson, String scriptName,
List<DSpaceCommandLineParameter> parameters) throws SQLException {
Process process = new Process();
process.setEPerson(ePerson);
process.setName(scriptName);
process.setParameters(DSpaceCommandLineParameter.concatenate(parameters));
process.setCreationTime(new Date());
Process createdProcess = processDAO.create(context, process);
log.info(LogManager.getHeader(context, "process_create",
"Process has been created for eperson with email " + ePerson.getEmail()
+ " with ID " + createdProcess.getID() + " and scriptName " +
scriptName + " and parameters " + parameters));
return createdProcess;
}
@Override
public Process find(Context context, int processId) throws SQLException {
return processDAO.findByID(context, Process.class, processId);
}
@Override
public List<Process> findAll(Context context) throws SQLException {
return processDAO.findAll(context, Process.class);
}
@Override
public List<Process> findAll(Context context, int limit, int offset) throws SQLException {
return processDAO.findAll(context, limit, offset);
}
@Override
public List<Process> findAllSortByScript(Context context) throws SQLException {
return processDAO.findAllSortByScript(context);
}
@Override
public List<Process> findAllSortByStartTime(Context context) throws SQLException {
List<Process> processes = findAll(context);
Comparator<Process> comparing = Comparator
.comparing(Process::getStartTime, Comparator.nullsLast(Comparator.naturalOrder()));
comparing = comparing.thenComparing(Process::getID);
processes.sort(comparing);
return processes;
}
@Override
public void start(Context context, Process process) throws SQLException {
process.setProcessStatus(ProcessStatus.RUNNING);
process.setStartTime(new Date());
update(context, process);
log.info(LogManager.getHeader(context, "process_start", "Process with ID " + process.getID()
+ " and name " + process.getName() + " has started"));
}
@Override
public void fail(Context context, Process process) throws SQLException {
process.setProcessStatus(ProcessStatus.FAILED);
process.setFinishedTime(new Date());
update(context, process);
log.info(LogManager.getHeader(context, "process_fail", "Process with ID " + process.getID()
+ " and name " + process.getName() + " has failed"));
}
@Override
public void complete(Context context, Process process) throws SQLException {
process.setProcessStatus(ProcessStatus.COMPLETED);
process.setFinishedTime(new Date());
update(context, process);
log.info(LogManager.getHeader(context, "process_complete", "Process with ID " + process.getID()
+ " and name " + process.getName() + " has been completed"));
}
@Override
public void delete(Context context, Process process) throws SQLException {
processDAO.delete(context, process);
log.info(LogManager.getHeader(context, "process_delete", "Process with ID " + process.getID()
+ " and name " + process.getName() + " has been deleted"));
}
@Override
public void update(Context context, Process process) throws SQLException {
processDAO.save(context, process);
}
@Override
public List<DSpaceCommandLineParameter> getParameters(Process process) {
if (StringUtils.isBlank(process.getParameters())) {
return Collections.emptyList();
}
String[] parameterArray = process.getParameters().split(Pattern.quote(DSpaceCommandLineParameter.SEPARATOR));
List<DSpaceCommandLineParameter> parameterList = new ArrayList<>();
for (String parameter : parameterArray) {
parameterList.add(new DSpaceCommandLineParameter(parameter));
}
return parameterList;
}
public int countTotal(Context context) throws SQLException {
return processDAO.countRows(context);
}
}

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.scripts;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.dspace.core.Context;
import org.dspace.scripts.service.ScriptService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* The implementation for the {@link ScriptService}
*/
public class ScriptServiceImpl implements ScriptService {
@Autowired
private List<DSpaceRunnable> dSpaceRunnables;
@Override
public DSpaceRunnable getScriptForName(String name) {
return dSpaceRunnables.stream()
.filter(dSpaceRunnable -> StringUtils.equalsIgnoreCase(dSpaceRunnable.getName(), name))
.findFirst()
.orElse(null);
}
@Override
public List<DSpaceRunnable> getDSpaceRunnables(Context context) {
return dSpaceRunnables.stream().filter(
dSpaceRunnable -> dSpaceRunnable.isAllowedToExecute(context)).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,41 @@
/**
* 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.scripts.factory;
import org.dspace.scripts.service.ProcessService;
import org.dspace.scripts.service.ScriptService;
import org.dspace.services.factory.DSpaceServicesFactory;
/**
* Abstract factory to get services for the Script workload, use ScriptServiceFactory.getInstance() to retrieve an
* implementation
*
*/
public abstract class ScriptServiceFactory {
/**
* This method will return an instance of the ScriptService
* @return An instance of the ScriptService
*/
public abstract ScriptService getScriptService();
/**
* This method will return an instance of the ProcessService
* @return An instance of the ProcessService
*/
public abstract ProcessService getProcessService();
/**
* Use this method to retrieve an implementation of the ScriptServiceFactory to use to retrieve the different beans
* @return An implementation of the ScriptServiceFactory
*/
public static ScriptServiceFactory getInstance() {
return DSpaceServicesFactory.getInstance().getServiceManager()
.getServiceByName("scriptServiceFactory", ScriptServiceFactory.class);
}
}

View File

@@ -0,0 +1,35 @@
/**
* 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.scripts.factory.impl;
import org.dspace.scripts.factory.ScriptServiceFactory;
import org.dspace.scripts.service.ProcessService;
import org.dspace.scripts.service.ScriptService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* The implementation for the {@link ScriptServiceFactory}
*/
public class ScriptServiceFactoryImpl extends ScriptServiceFactory {
@Autowired(required = true)
private ScriptService scriptService;
@Autowired(required = true)
private ProcessService processService;
@Override
public ScriptService getScriptService() {
return scriptService;
}
@Override
public ProcessService getProcessService() {
return processService;
}
}

View File

@@ -0,0 +1,81 @@
/**
* 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.scripts.handler;
import java.sql.SQLException;
import org.apache.commons.cli.Options;
/**
* This is an interface meant to be implemented by any DSpaceRunnableHandler to specify specific execution methods
* of the script depending on where it was called from
*/
public interface DSpaceRunnableHandler {
/**
* This method handles the start of the script
* @throws SQLException If something goes wrong
*/
public void start() throws SQLException;
/**
* This method handles the completion of the script
* @throws SQLException If something goes wrong
*/
public void handleCompletion() throws SQLException;
/**
* This method handles an exception thrown by the script
* @param e The exception thrown by the script
*/
public void handleException(Exception e);
/**
* This method handles an exception thrown by the script
* @param message The String message for the exception thrown by the script
*/
public void handleException(String message);
/**
* This method handles an exception thrown by the script
* @param message The String message for the exception thrown by the script
* @param e The exception thrown by the script
*/
public void handleException(String message, Exception e);
/**
* This method will perform the debug logging of the message given
* @param message The message to be logged as debug
*/
public void logDebug(String message);
/**
* This method will perform the info logging of the message given
* @param message The message to be logged as info
*/
public void logInfo(String message);
/**
* This method will perform the warning logging of the message given
* @param message The message to be logged as warning
*/
public void logWarning(String message);
/**
* This method will perform the error logging of the message given
* @param message The message to be logged as an error
*/
public void logError(String message);
/**
* This method will print the help for the options and name
* @param options The options for the script
* @param name The name of the script
*/
public void printHelp(Options options, String name);
}

View File

@@ -0,0 +1,87 @@
/**
* 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.scripts.handler.impl;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.logging.log4j.Logger;
import org.dspace.scripts.handler.DSpaceRunnableHandler;
/**
* This is an implementation for the CommandLineDSpaceRunnables which means that these implementations
* are used by DSpaceRunnables which are called from the CommandLine
*/
public class CommandLineDSpaceRunnableHandler implements DSpaceRunnableHandler {
private static final Logger log = org.apache.logging.log4j.LogManager
.getLogger(CommandLineDSpaceRunnableHandler.class);
@Override
public void start() {
System.out.println("The script has started");
}
@Override
public void handleCompletion() {
System.out.println("The script has completed");
}
@Override
public void handleException(Exception e) {
handleException(null, e);
}
@Override
public void handleException(String message) {
handleException(message, null);
}
@Override
public void handleException(String message, Exception e) {
if (message != null) {
System.err.println(message);
log.error(message);
}
if (e != null) {
e.printStackTrace();
log.error(e.getMessage(), e);
}
System.exit(1);
}
@Override
public void logDebug(String message) {
log.debug(message);
}
@Override
public void logInfo(String message) {
System.out.println(message);
log.info(message);
}
@Override
public void logWarning(String message) {
System.out.println(message);
log.warn(message);
}
@Override
public void logError(String message) {
System.err.println(message);
log.error(message);
}
@Override
public void printHelp(Options options, String name) {
if (options != null) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(name, options);
}
}
}

View File

@@ -0,0 +1,139 @@
/**
* 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.scripts.service;
import java.sql.SQLException;
import java.util.List;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.scripts.DSpaceCommandLineParameter;
import org.dspace.scripts.Process;
/**
* An interface for the ProcessService with methods regarding the Process workload
*/
public interface ProcessService {
/**
* This method will create a Process object in the database
* @param context The relevant DSpace context
* @param ePerson The ePerson for which this process will be created on
* @param scriptName The script name to be used for the process
* @param parameters The parameters to be used for the process
* @return The created process
* @throws SQLException If something goes wrong
*/
public Process create(Context context, EPerson ePerson, String scriptName,
List<DSpaceCommandLineParameter> parameters) throws SQLException;
/**
* This method will retrieve a Process object from the Database with the given ID
* @param context The relevant DSpace context
* @param processId The process id on which we'll search for in the database
* @return The process that holds the given process id
* @throws SQLException If something goes wrong
*/
public Process find(Context context, int processId) throws SQLException;
/**
* Returns a list of all Process objects in the database
* @param context The relevant DSpace context
* @return The list of all Process objects in the Database
* @throws SQLException If something goes wrong
*/
public List<Process> findAll(Context context) throws SQLException;
/**
* Returns a list of all Process objects in the database
* @param context The relevant DSpace context
* @param limit The limit for the amount of Processes returned
* @param offset The offset for the Processes to be returned
* @return The list of all Process objects in the Database
* @throws SQLException If something goes wrong
*/
public List<Process> findAll(Context context, int limit, int offset) throws SQLException;
/**
* Returns a list of all Process objects in the database sorted by script name
* @param context The relevant DSpace context
* @return The list of all Process objects in the database sorted by script name
* @throws SQLException If something goes wrong
*/
public List<Process> findAllSortByScript(Context context) throws SQLException;
/**
* Returns a list of all Process objects in the database sorted by start time
* The most recent one will be shown first
* @param context The relevant DSpace context
* @return The list of all Process objects sorted by start time
* @throws SQLException If something goes wrong
*/
public List<Process> findAllSortByStartTime(Context context) throws SQLException;
/**
* This method will perform the logic needed to update the Process object in the database to represent a
* started state. A started state refers to {@link org.dspace.content.ProcessStatus#RUNNING}
* @param context The relevant DSpace context
* @param process The Process object to be updated
* @throws SQLException If something goes wrong
*/
public void start(Context context, Process process) throws SQLException;
/**
* This method will perform the logic needed to update the Process object in the database to represent
* a failed state
* @param context The relevant DSpace context
* @param process The Process object to be updated
* @throws SQLException If something goes wrong
*/
public void fail(Context context, Process process) throws SQLException;
/**
* This method will perform the logic needed to update the Process object in the database to represent
* a complete state
* @param context The relevant DSpace context
* @param process The Process object to be updated
* @throws SQLException If something goes wrong
*/
public void complete(Context context, Process process) throws SQLException;
/**
* This method will delete the given Process object from the database
* @param context The relevant DSpace context
* @param process The Process object to be deleted
* @throws SQLException If something goes wrong
*/
public void delete(Context context, Process process) throws SQLException;
/**
* This method will be used to update the given Process object in the database
* @param context The relevant DSpace context
* @param process The Process object to be updated
* @throws SQLException If something goes wrong
*/
public void update(Context context, Process process) throws SQLException;
/**
* This method will retrieve the list of parameters from the Process in its String format and it will parse
* these parameters to a list of {@link DSpaceCommandLineParameter} objects for better usability throughout DSpace
* @param process The Process object for which we'll return the parameters
* @return The list of parsed parameters from the Process object
*/
public List<DSpaceCommandLineParameter> getParameters(Process process);
/**
* Returns the total amount of Process objects in the dataase
* @param context The relevant DSpace context
* @return An integer that describes the amount of Process objects in the database
* @throws SQLException If something goes wrong
*/
int countTotal(Context context) throws SQLException;
}

View File

@@ -0,0 +1,33 @@
/**
* 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.scripts.service;
import java.util.List;
import org.dspace.core.Context;
import org.dspace.scripts.DSpaceRunnable;
/**
* This service will deal with logic to handle DSpaceRunnable objects
*/
public interface ScriptService {
/**
* This method will return the DSpaceRunnable that has the name that's equal to the name given in the parameters
* @param name The name that the script has to match
* @return The matching DSpaceRunnable script
*/
DSpaceRunnable getScriptForName(String name);
/**
* This method will return a list of DSpaceRunnable objects for which the given Context is authorized to use them
* @param context The relevant DSpace context
* @return The list of accessible DSpaceRunnable scripts for this context
*/
List<DSpaceRunnable> getDSpaceRunnables(Context context);
}

View File

@@ -189,16 +189,19 @@ ALTER TABLE item2bundle add primary key (item_id,bundle_id);
--Migrate Bundle2Bitsteam
ALTER TABLE bundle2bitstream ALTER COLUMN bundle_id rename to bundle_legacy_id;
ALTER TABLE bundle2bitstream ALTER COLUMN bitstream_id rename to bitstream_legacy_id;
ALTER TABLE bundle2bitstream ALTER COLUMN bitstream_order rename to bitstream_order_legacy;
ALTER TABLE bundle2bitstream ADD COLUMN bundle_id UUID NOT NULL;
ALTER TABLE bundle2bitstream ADD CONSTRAINT bundle2bitstream_bundle_id_fk FOREIGN KEY (bundle_id) REFERENCES bundle;
ALTER TABLE bundle2bitstream ADD COLUMN bitstream_id UUID NOT NULL;
ALTER TABLE bundle2bitstream ADD CONSTRAINT bundle2bitstream_bitstream_id_fk FOREIGN KEY (bitstream_id) REFERENCES bitstream;
ALTER TABLE bundle2bitstream ADD COLUMN bitstream_order INTEGER NOT NULL;
UPDATE bundle2bitstream SET bundle_id = (SELECT bundle.uuid FROM bundle WHERE bundle2bitstream.bundle_legacy_id = bundle.bundle_id);
UPDATE bundle2bitstream SET bitstream_id = (SELECT bitstream.uuid FROM bitstream WHERE bundle2bitstream.bitstream_legacy_id = bitstream.bitstream_id);
ALTER TABLE bundle2bitstream DROP COLUMN bundle_legacy_id;
ALTER TABLE bundle2bitstream DROP COLUMN bitstream_legacy_id;
ALTER TABLE bundle2bitstream DROP COLUMN bitstream_order_legacy;
ALTER TABLE bundle2bitstream DROP COLUMN id;
ALTER TABLE bundle2bitstream add primary key (bitstream_id,bundle_id);
ALTER TABLE bundle2bitstream add primary key (bitstream_id,bundle_id,bitstream_order);
-- Migrate item

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,40 @@
--
-- 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/
--
-- ===============================================================
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
--
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
-- http://flywaydb.org/
-- ===============================================================
CREATE SEQUENCE process_id_seq;
CREATE TABLE process
(
process_id INTEGER NOT NULL PRIMARY KEY,
user_id UUID NOT NULL,
start_time TIMESTAMP,
finished_time TIMESTAMP,
creation_time TIMESTAMP NOT NULL,
script VARCHAR(256) NOT NULL,
status VARCHAR(32),
parameters VARCHAR(512)
);
CREATE TABLE process2bitstream
(
process_id INTEGER REFERENCES process(process_id),
bitstream_id UUID REFERENCES bitstream(uuid),
CONSTRAINT PK_process2bitstream PRIMARY KEY (process_id, bitstream_id)
);
CREATE INDEX process_user_id_idx ON process(user_id);
CREATE INDEX process_status_idx ON process(status);
CREATE INDEX process_name_idx on process(script);
CREATE INDEX process_start_time_idx on process(start_time);

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,40 @@
--
-- 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/
--
-- ===============================================================
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
--
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
-- http://flywaydb.org/
-- ===============================================================
CREATE SEQUENCE process_id_seq;
CREATE TABLE process
(
process_id INTEGER NOT NULL PRIMARY KEY,
user_id RAW(16) NOT NULL,
start_time TIMESTAMP,
finished_time TIMESTAMP,
creation_time TIMESTAMP NOT NULL,
script VARCHAR(256) NOT NULL,
status VARCHAR(32),
parameters VARCHAR(512)
);
CREATE TABLE process2bitstream
(
process_id INTEGER REFERENCES process(process_id),
bitstream_id RAW(16) REFERENCES bitstream(uuid),
CONSTRAINT PK_process2bitstream PRIMARY KEY (process_id, bitstream_id)
);
CREATE INDEX process_user_id_idx ON process(user_id);
CREATE INDEX process_status_idx ON process(status);
CREATE INDEX process_name_idx on process(script);
CREATE INDEX process_start_time_idx on process(start_time);

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

@@ -0,0 +1,40 @@
--
-- 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/
--
-- ===============================================================
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
--
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
-- http://flywaydb.org/
-- ===============================================================
CREATE SEQUENCE process_id_seq;
CREATE TABLE process
(
process_id INTEGER NOT NULL PRIMARY KEY,
user_id UUID NOT NULL,
start_time TIMESTAMP,
finished_time TIMESTAMP,
creation_time TIMESTAMP NOT NULL,
script VARCHAR(256) NOT NULL,
status VARCHAR(32),
parameters VARCHAR(512)
);
CREATE TABLE process2bitstream
(
process_id INTEGER REFERENCES process(process_id),
bitstream_id UUID REFERENCES bitstream(uuid),
CONSTRAINT PK_process2bitstream PRIMARY KEY (process_id, bitstream_id)
);
CREATE INDEX process_user_id_idx ON process(user_id);
CREATE INDEX process_status_idx ON process(status);
CREATE INDEX process_name_idx on process(script);
CREATE INDEX process_start_time_idx on process(start_time);

View File

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

View File

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

View File

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

View File

@@ -25,6 +25,9 @@
# SERVER CONFIGURATION #
##########################
# Spring boot test by default mock the server on the localhost (80)
dspace.baseUrl = http://localhost
# DSpace installation directory.
# 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)

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="indexClient" class="org.dspace.discovery.IndexClient" scope="prototype">
<property name="name" value="index-discovery"/>
<property name="description" value="Update Discovery Solr Search Index"/>
</bean>
<bean id="MockScript" class="org.dspace.scripts.impl.MockDSpaceRunnableScript" scope="prototype">
<property name="name" value="mock-script" />
<property name="description" value="Mocking a script for testing purposes" />
</bean>
</beans>

View File

@@ -23,6 +23,10 @@
<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"/>-->
<!-- Statistics services are both lazy loaded (by name), as you are likely just using ONE of them and not both -->

View File

@@ -14,11 +14,12 @@
<!-- Each form set contains an ordered set of pages; each page defines -->
<!-- one submission metadata entry screen. Each page has an ordered list -->
<!-- of field definitions, Each field definition corresponds to one -->
<!-- metadata entry (a so-called row), which has a DC element name, a -->
<!-- metadata entry (a so-called row), which has a DC element name, a -->
<!-- displayed label, a text string prompt which is called a hint, and -->
<!-- an input-type. Each field also may hold optional elements: DC -->
<!-- qualifier name, a repeatable flag, and a text string whose presence -->
<!-- serves as a 'this field is required' flag. -->
<!-- qualifier name, a repeatable flag, an optional name-variants allowed -->
<!-- flag, and a text string whose presence serves as a -->
<!-- 'this field is required' flag. -->
<form-definitions>
<form name="bitstream-metadata">
@@ -53,6 +54,7 @@
<relationship-type>isAuthorOfPublication</relationship-type>
<search-configuration>personConfiguration</search-configuration>
<repeatable>true</repeatable>
<name-variants>true</name-variants>
<label>Author</label>
<hint>Add an author</hint>
<linked-metadata-field>

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

View File

@@ -0,0 +1,216 @@
/**
* 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()));
}
@Test
public void testGetNextRightPlace() throws Exception {
assertThat(relationshipService.findNextRightPlaceByRightItem(context, authorItem), equalTo(0));
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();
assertThat(relationshipService.findNextRightPlaceByRightItem(context, authorItem), equalTo(1));
context.turnOffAuthorisationSystem();
Community community = communityService.create(null, context);
Collection col = collectionService.create(context, community);
WorkspaceItem is = workspaceItemService.create(context, col, false);
Item secondItem = installItemService.installItem(context, is);
itemService.addMetadata(context, secondItem, "relationship", "type", null, null, "Publication");
Relationship secondRelationship = relationshipService.create(context, secondItem, authorItem,
isAuthorOfPublication, 0, 0);
context.restoreAuthSystemState();
assertThat(relationshipService.findNextRightPlaceByRightItem(context, authorItem), equalTo(2));
}
@Test
public void testGetNextLeftPlace() throws Exception {
assertThat(relationshipService.findNextLeftPlaceByLeftItem(context, item), equalTo(0));
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();
assertThat(relationshipService.findNextLeftPlaceByLeftItem(context, item), equalTo(1));
context.turnOffAuthorisationSystem();
Community community = communityService.create(null, context);
Collection col = collectionService.create(context, community);
WorkspaceItem is = workspaceItemService.create(context, col, false);
Item secondAuthor = installItemService.installItem(context, is);
itemService.addMetadata(context, secondAuthor, "relationship", "type", null, null, "Author");
itemService.addMetadata(context, secondAuthor, "person", "familyName", null, null, "familyName");
itemService.addMetadata(context, secondAuthor, "person", "givenName", null, null, "firstName");
Relationship secondRelationship = relationshipService.create(context, item, secondAuthor,
isAuthorOfPublication, 0, 0);
context.restoreAuthSystemState();
assertThat(relationshipService.findNextLeftPlaceByLeftItem(context, item), equalTo(2));
}
}

View File

@@ -0,0 +1,428 @@
/**
* 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.EntityTypeService;
import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.MetadataValueService;
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 RelationshipServiceImplPlaceTest extends AbstractUnitTest {
private static final Logger log = org.apache.logging.log4j.LogManager
.getLogger(RelationshipServiceImplPlaceTest.class);
protected RelationshipService relationshipService = ContentServiceFactory.getInstance().getRelationshipService();
protected RelationshipTypeService relationshipTypeService = ContentServiceFactory.getInstance()
.getRelationshipTypeService();
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();
protected MetadataValueService metadataValueService = ContentServiceFactory.getInstance().getMetadataValueService();
Community community;
Collection col;
Item item;
Item authorItem;
RelationshipType isAuthorOfPublication;
EntityType publicationEntityType;
EntityType authorEntityType;
String authorQualifier = "author";
String contributorElement = "contributor";
String dcSchema = "dc";
/**
* This method will be run before every test as per @Before. It will
* initialize resources required for the tests.
*/
@Before
@Override
public void init() {
super.init();
try {
context.turnOffAuthorisationSystem();
community = communityService.create(null, context);
col = collectionService.create(context, community);
WorkspaceItem is = workspaceItemService.create(context, col, false);
WorkspaceItem authorIs = workspaceItemService.create(context, col, false);
item = installItemService.installItem(context, is);
itemService.addMetadata(context, item, "relationship", "type", null, null, "Publication");
authorItem = installItemService.installItem(context, authorIs);
itemService.addMetadata(context, authorItem, "relationship", "type", null, null, "Person");
itemService.addMetadata(context, authorItem, "person", "familyName", null, null, "familyName");
itemService.addMetadata(context, authorItem, "person", "givenName", null, null, "firstName");
publicationEntityType = entityTypeService.create(context, "Publication");
authorEntityType = entityTypeService.create(context, "Person");
isAuthorOfPublication = relationshipTypeService
.create(context, publicationEntityType, authorEntityType,
"isAuthorOfPublication", "isPublicationOfAuthor",
null, null, null, null);
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.
*/
@After
@Override
public void destroy() {
context.abort();
super.destroy();
}
/**
* This test will test the use case of having an item to which we add some metadata. After that, we'll add a single
* relationship to this Item. We'll test whether the places are correct, in this case it'll be the two metadata
* values that we created first, has to have place 0 and 1. The Relationship that we just created needs to have
* leftPlace 2 and the metadata value resulting from that Relationship needs to also have place 2.
* Once these assertions succeed, we basically repeat said process with new metadata values and a new relationship.
* We then test if the old assertions still hold true like they should and that the new ones behave as expected
* as well.
* @throws Exception If something goes wrong
*/
@Test
public void addMetadataAndRelationshipTest() throws Exception {
context.turnOffAuthorisationSystem();
// Here we add the first set of metadata to the item
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, one");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, two");
// Here we create the first Relationship to the item
Relationship relationship = relationshipService
.create(context, item, authorItem, isAuthorOfPublication, -1, -1);
context.restoreAuthSystemState();
// The code below performs the mentioned assertions to ensure the place is correct
List<MetadataValue> list = itemService
.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
assertThat(list.size(), equalTo(3));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, two", null, 1, list.get(1));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 2, list.get(2));
assertThat(relationship.getLeftPlace(), equalTo(2));
context.turnOffAuthorisationSystem();
// This is where we add the second set of metadata values
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, three");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, four");
// Here we create an Item so that we can create another relationship with this item
WorkspaceItem authorIs = workspaceItemService.create(context, col, false);
Item secondAuthorItem = installItemService.installItem(context, authorIs);
itemService.addMetadata(context, secondAuthorItem, "relationship", "type", null, null, "Person");
itemService.addMetadata(context, secondAuthorItem, "person", "familyName", null, null, "familyNameTwo");
itemService.addMetadata(context, secondAuthorItem, "person", "givenName", null, null, "firstNameTwo");
Relationship relationshipTwo = relationshipService
.create(context, item, secondAuthorItem, isAuthorOfPublication, -1, -1);
context.restoreAuthSystemState();
// Here we retrieve the list of metadata again to perform the assertions on the places below as mentioned
list = itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, two", null, 1, list.get(1));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 2, list.get(2));
assertThat(relationship.getLeftPlace(), equalTo(2));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, three", null, 3, list.get(3));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, four", null, 4, list.get(4));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyNameTwo, firstNameTwo",
"virtual::" + relationshipTwo.getID(), 5, list.get(5));
assertThat(relationshipTwo.getLeftPlace(), equalTo(5));
}
/**
* This test is virtually the same as above, only this time we'll add Relationships with leftPlaces already set
* equal to what they HAVE to be. So in the first test addMetadataAndRelationshipTest, we didn't specify a place
* and left it up to the Service to determine it, here we provide a correct place already.
* We perform the exact same logic except that we give a proper place already to the Relationships and we
* perform the same checks
* @throws Exception If something goes wrong
*/
@Test
public void AddMetadataAndRelationshipWithSpecificPlaceTest() throws Exception {
context.turnOffAuthorisationSystem();
// Here we add the first set of metadata to the item
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, one");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, two");
// Here we create the first Relationship to the item with the specific leftPlace: 2
Relationship relationship = relationshipService.create(context, item, authorItem, isAuthorOfPublication, 2, -1);
context.restoreAuthSystemState();
// The code below performs the mentioned assertions to ensure the place is correct
List<MetadataValue> list = itemService
.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
assertThat(list.size(), equalTo(3));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, two", null, 1, list.get(1));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 2, list.get(2));
assertThat(relationship.getLeftPlace(), equalTo(2));
context.turnOffAuthorisationSystem();
// This is where we add the second set of metadata values
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, three");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, four");
// Here we create an Item so that we can create another relationship with this item. We'll give this
// Relationship a specific place as well
WorkspaceItem authorIs = workspaceItemService.create(context, col, false);
Item secondAuthorItem = installItemService.installItem(context, authorIs);
itemService.addMetadata(context, secondAuthorItem, "relationship", "type", null, null, "Person");
itemService.addMetadata(context, secondAuthorItem, "person", "familyName", null, null, "familyNameTwo");
itemService.addMetadata(context, secondAuthorItem, "person", "givenName", null, null, "firstNameTwo");
Relationship relationshipTwo = relationshipService
.create(context, item, secondAuthorItem, isAuthorOfPublication, 5, -1);
context.restoreAuthSystemState();
// Here we retrieve the list of metadata again to perform the assertions on the places below as mentioned
list = itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, two", null, 1, list.get(1));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 2, list.get(2));
assertThat(relationship.getLeftPlace(), equalTo(2));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, three", null, 3, list.get(3));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, four", null, 4, list.get(4));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyNameTwo, firstNameTwo",
"virtual::" + relationshipTwo.getID(), 5, list.get(5));
assertThat(relationshipTwo.getLeftPlace(), equalTo(5));
}
/**
* In this test, our goal will be to add a bunch of metadata values to then remove one of them. We'll check the list
* of metadata values for the item and check that the places have not been altered for the metadata values IF an
* item.update hadn't been called yet. We'll then create a Relationship (by which an item.update will be called)
* and then we check that the places are set correctly.
* We then repeat this process once more and check that everything works as intended
* @throws Exception
*/
@Test
public void AddAndRemoveMetadataAndRelationshipsTest() throws Exception {
context.turnOffAuthorisationSystem();
// Here we add the first set of metadata to the item
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, one");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, two");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, three");
// Get a specific metadatavlaue to remove
MetadataValue metadataValueToRemove = itemService.getMetadata(item, "dc", "contributor", "author", Item.ANY)
.get(1);
// Remove the actual metadata value
item.removeMetadata(metadataValueToRemove);
metadataValueService.delete(context, metadataValueToRemove);
context.restoreAuthSystemState();
// Retrieve the list of mdv again
List<MetadataValue> list = itemService
.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
// Verify we only have 2 mdv left
assertThat(list.size(), equalTo(2));
// Check that these places are still intact after the deletion as the place doesn't get updated until an
// item.update has been called
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, three", null, 2, list.get(1));
context.turnOffAuthorisationSystem();
// Create a relationship with this item with a spcific place
Relationship relationship = relationshipService.create(context, item, authorItem, isAuthorOfPublication, 1, -1);
context.restoreAuthSystemState();
// Retrieve the list again and verify that the creation of the Relationship added an additional mdv
list = itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
assertThat(list.size(), equalTo(3));
// Assert that the mdv are well placed
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 1, list.get(1));
assertThat(relationship.getLeftPlace(), equalTo(1));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, three", null, 2, list.get(2));
context.turnOffAuthorisationSystem();
// Add two extra mdv
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, four");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, five");
//This is author "test, four" that we're removing
metadataValueToRemove = itemService.getMetadata(item, "dc", "contributor", "author", Item.ANY).get(3);
item.removeMetadata(metadataValueToRemove);
metadataValueService.delete(context, metadataValueToRemove);
context.restoreAuthSystemState();
list = itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
// Check that these places are still intact after the deletion as the place doesn't get updated until an
// item.update has been called
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 1, list.get(1));
assertThat(relationship.getLeftPlace(), equalTo(1));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, three", null, 2, list.get(2));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, five", null, 4, list.get(3));
context.turnOffAuthorisationSystem();
// Create an additional item for another relationship
WorkspaceItem authorIs = workspaceItemService.create(context, col, false);
Item secondAuthorItem = installItemService.installItem(context, authorIs);
itemService.addMetadata(context, secondAuthorItem, "relationship", "type", null, null, "Person");
itemService.addMetadata(context, secondAuthorItem, "person", "familyName", null, null, "familyNameTwo");
itemService.addMetadata(context, secondAuthorItem, "person", "givenName", null, null, "firstNameTwo");
Relationship relationshipTwo = relationshipService
.create(context, item, secondAuthorItem, isAuthorOfPublication, 3, -1);
context.restoreAuthSystemState();
// Check that the other mdv are still okay and that the creation of the relationship added
// another correct mdv to the item
list = itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 1, list.get(1));
assertThat(relationship.getLeftPlace(), equalTo(1));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, three", null, 2, list.get(2));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyNameTwo, firstNameTwo",
"virtual::" + relationshipTwo.getID(), 3, list.get(3));
assertThat(relationshipTwo.getLeftPlace(), equalTo(3));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, five", null, 4, list.get(4));
}
@Test
public void AddAndUpdateMetadataAndRelationshipsTest() throws Exception {
context.turnOffAuthorisationSystem();
// Add metadata and relationships to the item
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, one");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, two");
itemService.addMetadata(context, item, dcSchema, contributorElement, authorQualifier, null, "test, three");
Relationship relationship = relationshipService
.create(context, item, authorItem, isAuthorOfPublication, -1, -1);
context.restoreAuthSystemState();
// Get the list of mdv and assert that they're correct
List<MetadataValue> list = itemService
.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
assertThat(list.size(), equalTo(4));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, two", null, 1, list.get(1));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, three", null, 2, list.get(2));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 3, list.get(3));
assertThat(relationship.getLeftPlace(), equalTo(3));
context.turnOffAuthorisationSystem();
MetadataValue metadataValueToUpdate = itemService.getMetadata(item, "dc", "contributor", "author", Item.ANY)
.get(1);
// Switching the places of this relationship and metadata value to verify in the test later on that this
// updating works
metadataValueToUpdate.setPlace(3);
metadataValueService.update(context, metadataValueToUpdate);
relationship.setLeftPlace(1);
relationshipService.update(context, relationship);
context.restoreAuthSystemState();
// Retrieve the list again and verify that the updating did indeed work
list = itemService.getMetadata(item, dcSchema, contributorElement, authorQualifier, Item.ANY);
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, one", null, 0, list.get(0));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, two", null, 3, list.get(3));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "test, three", null, 2, list.get(2));
assertMetadataValue(authorQualifier, contributorElement, dcSchema, "familyName, firstName",
"virtual::" + relationship.getID(), 1, list.get(1));
assertThat(relationship.getLeftPlace(), equalTo(1));
}
private void assertMetadataValue(String authorQualifier, String contributorElement, String dcSchema, String value,
String authority, int place, MetadataValue metadataValue) {
assertThat(metadataValue.getValue(), equalTo(value));
assertThat(metadataValue.getMetadataField().getMetadataSchema().getName(), equalTo(dcSchema));
assertThat(metadataValue.getMetadataField().getElement(), equalTo(contributorElement));
assertThat(metadataValue.getMetadataField().getQualifier(), equalTo(authorQualifier));
assertThat(metadataValue.getAuthority(), equalTo(authority));
assertThat(metadataValue.getPlace(), equalTo(place));
}
}

View File

@@ -66,7 +66,7 @@ public class RelationshipServiceImplTest {
@Test
public void testFindAll() throws Exception {
// 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
assertEquals("TestFindAll 0", relationshipsList, relationshipService.findAll(context));
}
@@ -84,23 +84,22 @@ public class RelationshipServiceImplTest {
RelationshipType hasDog = new RelationshipType();
RelationshipType hasFather = new RelationshipType();
RelationshipType hasMother = new RelationshipType();
hasDog.setLeftLabel("hasDog");
hasDog.setRightLabel("isDogOf");
hasFather.setLeftLabel("hasFather");
hasFather.setRightLabel("isFatherOf");
hasMother.setLeftLabel("hasMother");
hasMother.setRightLabel("isMotherOf");
hasDog.setLeftwardType("hasDog");
hasDog.setRightwardType("isDogOf");
hasFather.setLeftwardType("hasFather");
hasFather.setRightwardType("isFatherOf");
hasMother.setLeftwardType("hasMother");
hasMother.setRightwardType("isMotherOf");
relationshipTest.add(getRelationship(cindy, spot, hasDog,0,0));
relationshipTest.add(getRelationship(cindy, jasper, hasDog,0,1));
relationshipTest.add(getRelationship(cindy, hank, hasFather,0,0));
relationshipTest.add(getRelationship(fred, cindy, hasMother,0,0));
relationshipTest.add(getRelationship(bob, cindy, hasMother,1,0));
when(relationshipService.findByItem(context, cindy)).thenReturn(relationshipTest);
when(relationshipDAO.findByItem(context, cindy)).thenReturn(relationshipTest);
when(relationshipService.findByItem(context, cindy, -1, -1)).thenReturn(relationshipTest);
// 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);
assertEquals("TestFindByItem 0", relationshipTest, results);
@@ -115,11 +114,11 @@ public class RelationshipServiceImplTest {
Item item = mock(Item.class);
// Mock DAO to return mocked left place as 0
when(relationshipDAO.findLeftPlaceByLeftItem(context, item)).thenReturn(0);
when(relationshipDAO.findNextLeftPlaceByLeftItem(context, item)).thenReturn(0);
// The left place reported from out mocked item should match the DAO's report of the left place
assertEquals("TestFindLeftPlaceByLeftItem 0", relationshipDAO.findLeftPlaceByLeftItem(context, item),
relationshipService.findLeftPlaceByLeftItem(context, item));
assertEquals("TestFindLeftPlaceByLeftItem 0", relationshipDAO.findNextLeftPlaceByLeftItem(context, item),
relationshipService.findNextLeftPlaceByLeftItem(context, item));
}
@Test
@@ -128,11 +127,11 @@ public class RelationshipServiceImplTest {
Item item = mock(Item.class);
// Mock lower level DAO to return mocked right place as 0
when(relationshipDAO.findRightPlaceByRightItem(context, item)).thenReturn(0);
when(relationshipDAO.findNextRightPlaceByRightItem(context, item)).thenReturn(0);
// The right place reported from out mocked item should match the DAO's report of the right place
assertEquals("TestFindRightPlaceByRightItem 0", relationshipDAO.findRightPlaceByRightItem(context, item),
relationshipService.findRightPlaceByRightItem(context, item));
assertEquals("TestFindRightPlaceByRightItem 0", relationshipDAO.findNextRightPlaceByRightItem(context, item),
relationshipService.findNextRightPlaceByRightItem(context, item));
}
@Test
@@ -194,8 +193,8 @@ public class RelationshipServiceImplTest {
EntityType rightEntityType = mock(EntityType.class);
testRel.setLeftType(leftEntityType);
testRel.setRightType(rightEntityType);
testRel.setLeftLabel("Entitylabel");
testRel.setRightLabel("Entitylabel");
testRel.setLeftwardType("Entitylabel");
testRel.setRightwardType("Entitylabel");
metsList.add(metVal);
relationship = getRelationship(leftItem, rightItem, testRel, 0,0);
leftTypelist.add(relationship);
@@ -247,8 +246,8 @@ public class RelationshipServiceImplTest {
EntityType rightEntityType = mock(EntityType.class);
testRel.setLeftType(leftEntityType);
testRel.setRightType(rightEntityType);
testRel.setLeftLabel("Entitylabel");
testRel.setRightLabel("Entitylabel");
testRel.setLeftwardType("Entitylabel");
testRel.setRightwardType("Entitylabel");
testRel.setLeftMinCardinality(0);
testRel.setRightMinCardinality(0);
metsList.add(metVal);
@@ -271,6 +270,8 @@ public class RelationshipServiceImplTest {
when(metsList.get(0).getValue()).thenReturn("Entitylabel");
when(relationshipService.findByItemAndRelationshipType(context, leftItem, testRel, true))
.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(rightItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList);
when(relationshipDAO.create(any(), any())).thenReturn(relationship);
@@ -299,8 +300,8 @@ public class RelationshipServiceImplTest {
EntityType rightEntityType = mock(EntityType.class);
testRel.setLeftType(leftEntityType);
testRel.setRightType(rightEntityType);
testRel.setLeftLabel("Entitylabel");
testRel.setRightLabel("Entitylabel");
testRel.setLeftwardType("Entitylabel");
testRel.setRightwardType("Entitylabel");
testRel.setLeftMinCardinality(0);
testRel.setRightMinCardinality(0);
metsList.add(metVal);
@@ -321,6 +322,12 @@ public class RelationshipServiceImplTest {
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
* @param leftItem Relationship's left item

View File

@@ -51,8 +51,8 @@ public class RelationshipTypeTest {
firstRelationshipType.setId(1);
firstRelationshipType.setLeftType(mock(EntityType.class));
firstRelationshipType.setRightType(mock(EntityType.class));
firstRelationshipType.setLeftLabel("isAuthorOfPublication");
firstRelationshipType.setRightLabel("isPublicationOfAuthor");
firstRelationshipType.setLeftwardType("isAuthorOfPublication");
firstRelationshipType.setRightwardType("isPublicationOfAuthor");
firstRelationshipType.setLeftMinCardinality(0);
firstRelationshipType.setLeftMaxCardinality(null);
firstRelationshipType.setRightMinCardinality(0);
@@ -63,8 +63,8 @@ public class RelationshipTypeTest {
secondRelationshipType.setId(new Random().nextInt());
secondRelationshipType.setLeftType(mock(EntityType.class));
secondRelationshipType.setRightType(mock(EntityType.class));
secondRelationshipType.setLeftLabel("isProjectOfPerson");
secondRelationshipType.setRightLabel("isPersonOfProject");
secondRelationshipType.setLeftwardType("isProjectOfPerson");
secondRelationshipType.setRightwardType("isPersonOfProject");
secondRelationshipType.setLeftMinCardinality(0);
secondRelationshipType.setLeftMaxCardinality(null);
secondRelationshipType.setRightMinCardinality(0);
@@ -87,11 +87,11 @@ public class RelationshipTypeTest {
@Test
public void testRelationshipTypeFindByTypesAndLabels() throws Exception {
// Mock DAO to return our firstRelationshipType
when(relationshipTypeDAO.findByTypesAndLabels(any(), any(), any(), any(), any()))
when(relationshipTypeDAO.findbyTypesAndTypeName(any(), any(), any(), any(), any()))
.thenReturn(firstRelationshipType);
// 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", "mock");
@@ -107,7 +107,7 @@ public class RelationshipTypeTest {
mockedList.add(secondRelationshipType);
// 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()
List<RelationshipType> foundRelationshipTypes = relationshipTypeService.findAll(context);
@@ -118,16 +118,16 @@ public class RelationshipTypeTest {
}
@Test
public void testRelationshipTypeFindByLeftOrRightLabel() throws Exception {
public void testRelationshipTypeFindByLeftOrRightwardType() throws Exception {
// Declare objects utilized for this test
List<RelationshipType> mockedList = new LinkedList<>();
mockedList.add(firstRelationshipType);
// Mock DAO to return our mockedList
when(relationshipTypeDAO.findByLeftOrRightLabel(any(), any())).thenReturn(mockedList);
when(relationshipTypeDAO.findByLeftwardOrRightwardTypeName(context, "mock", -1, -1)).thenReturn(mockedList);
// Invoke findByLeftOrRightLabel()
List<RelationshipType> found = relationshipTypeService.findByLeftOrRightLabel(context, "mock");
// Invoke findByLeftwardOrRightwardTypeName()
List<RelationshipType> found = relationshipTypeService.findByLeftwardOrRightwardTypeName(context, "mock");
// Assert that our expected list contains our expected RelationshipType and nothing more
assertThat(found, notNullValue());
@@ -142,10 +142,11 @@ public class RelationshipTypeTest {
mockedList.add(firstRelationshipType);
// Mock DAO to return our mockedList
when(relationshipTypeDAO.findByEntityType(any(), any())).thenReturn(mockedList);
when(relationshipTypeDAO.findByEntityType(any(), any(), any(), any())).thenReturn(mockedList);
// 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
assertThat(found, notNullValue());
@@ -160,8 +161,8 @@ public class RelationshipTypeTest {
*/
private void checkRelationshipTypeValues(RelationshipType found, RelationshipType original) {
assertThat(found, notNullValue());
assertThat(found.getLeftLabel(), equalTo(original.getLeftLabel()));
assertThat(found.getRightLabel(), equalTo(original.getRightLabel()));
assertThat(found.getLeftwardType(), equalTo(original.getLeftwardType()));
assertThat(found.getRightwardType(), equalTo(original.getRightwardType()));
assertThat(found.getLeftType(), equalTo(original.getLeftType()));
assertThat(found.getRightType(), equalTo(original.getRightType()));
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 findNextLeftPlaceByLeftItem should return 0 given our test left Item itemOne.
*
* @throws Exception
*/
@Test
public void testFindNextLeftPlaceByLeftItem() throws Exception {
assertEquals("TestNextLeftPlaceByLeftItem 0", 1, relationshipService.findNextLeftPlaceByLeftItem(context,
itemOne));
}
/**
* Test findNextRightPlaceByRightItem should return 0 given our test right Item itemTwo.
*
* @throws Exception
*/
@Test
public void testFindNextRightPlaceByRightItem() throws Exception {
assertEquals("TestNextRightPlaceByRightItem 0", 1, relationshipService.findNextRightPlaceByRightItem(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);
EntityType entityType = mock(EntityType.class);
RelationshipType relationshipType = mock(RelationshipType.class);
related.setRelationshipTypeString("LeftLabel");
related.setRelationshipTypeString("LeftwardType");
relationshipTypeList.add(relationshipType);
relationshipList.add(relationship);
related.setPlace(0);
// Mock the state of objects utilized in getRelationsByLabel() to meet the success criteria of an invocation
when(item.getID()).thenReturn(UUID.randomUUID());
when(relationshipType.getLeftLabel()).thenReturn("LeftLabel");
when(relationshipType.getRightLabel()).thenReturn("RightLabel");
when(relationshipType.getLeftwardType()).thenReturn("LeftwardType");
when(relationshipType.getRightwardType()).thenReturn("RightwardType");
when(relationshipType.getLeftType()).thenReturn(entityType);
when(relationshipType.getRightType()).thenReturn(entityType);
when(entityService.getAllRelationshipTypes(context, entity)).thenReturn(relationshipTypeList);

View File

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

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