Merge remote-tracking branch 'dspace/master' into w2p-65267_delete-in-relationshipservice

This commit is contained in:
Peter Nijs
2019-11-26 17:28:22 +01:00
297 changed files with 10618 additions and 2443 deletions

View File

@@ -54,7 +54,13 @@ EXPOSE 8080 8009
ENV JAVA_OPTS=-Xmx2000m ENV JAVA_OPTS=-Xmx2000m
RUN mv /usr/local/tomcat/webapps/ROOT /usr/local/tomcat/webapps/ROOT.bk && \ # Run the "server" webapp off the /server path (e.g. http://localhost:8080/server/)
ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/ROOT && \ # and the v6.x (deprecated) REST API off the "/rest" path
ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/server && \ RUN ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/server && \
ln -s $DSPACE_INSTALL/webapps/rest /usr/local/tomcat/webapps/rest 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 ENV JAVA_OPTS=-Xmx2000m
RUN mv /usr/local/tomcat/webapps/ROOT /usr/local/tomcat/webapps/ROOT.bk && \ # Run the "server" webapp off the /server path (e.g. http://localhost:8080/server/)
ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/ROOT && \ # and the v6.x (deprecated) REST API off the "/rest" path
ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/server && \ RUN ln -s $DSPACE_INSTALL/webapps/server /usr/local/tomcat/webapps/server && \
ln -s $DSPACE_INSTALL/webapps/rest /usr/local/tomcat/webapps/rest 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 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

@@ -193,7 +193,7 @@ public class MetadataImport {
* @param workflowNotify If the workflows should be used, whether to send notifications or not * @param workflowNotify If the workflows should be used, whether to send notifications or not
* @param useTemplate Use collection template if create new item * @param useTemplate Use collection template if create new item
* @return An array of BulkEditChange elements representing the items that have changed * @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, public List<BulkEditChange> runImport(boolean change,
boolean useWorkflow, boolean useWorkflow,
@@ -402,13 +402,15 @@ public class MetadataImport {
// Add the metadata to the item // Add the metadata to the item
for (BulkEditMetadataValue dcv : whatHasChanged.getAdds()) { for (BulkEditMetadataValue dcv : whatHasChanged.getAdds()) {
itemService.addMetadata(c, item, dcv.getSchema(), if (!StringUtils.equals(dcv.getSchema(), MetadataSchemaEnum.RELATION.getName())) {
dcv.getElement(), itemService.addMetadata(c, item, dcv.getSchema(),
dcv.getQualifier(), dcv.getElement(),
dcv.getLanguage(), dcv.getQualifier(),
dcv.getValue(), dcv.getLanguage(),
dcv.getAuthority(), dcv.getValue(),
dcv.getConfidence()); dcv.getAuthority(),
dcv.getConfidence());
}
} }
//Add relations after all metadata has been processed //Add relations after all metadata has been processed
for (BulkEditMetadataValue dcv : whatHasChanged.getAdds()) { for (BulkEditMetadataValue dcv : whatHasChanged.getAdds()) {
@@ -778,8 +780,8 @@ public class MetadataImport {
} }
// Create the relationship // Create the relationship
int leftPlace = relationshipService.findLeftPlaceByLeftItem(c, leftItem) + 1; int leftPlace = relationshipService.findNextLeftPlaceByLeftItem(c, leftItem);
int rightPlace = relationshipService.findRightPlaceByRightItem(c, rightItem) + 1; int rightPlace = relationshipService.findNextRightPlaceByRightItem(c, rightItem);
Relationship persistedRelationship = relationshipService.create(c, leftItem, rightItem, Relationship persistedRelationship = relationshipService.create(c, leftItem, rightItem,
foundRelationshipType, leftPlace, rightPlace); foundRelationshipType, leftPlace, rightPlace);
relationshipService.update(c, persistedRelationship); relationshipService.update(c, persistedRelationship);

View File

@@ -13,6 +13,12 @@ import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import java.util.TreeMap; 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.DSpaceKernelImpl;
import org.dspace.servicemanager.DSpaceKernelInit; import org.dspace.servicemanager.DSpaceKernelInit;
import org.dspace.services.RequestService; import org.dspace.services.RequestService;
@@ -27,6 +33,9 @@ import org.jdom.input.SAXBuilder;
* @author Mark Diggory * @author Mark Diggory
*/ */
public class ScriptLauncher { public class ScriptLauncher {
private static final Logger log = Logger.getLogger(ScriptLauncher.class);
/** /**
* The service manager kernel * The service manager kernel
*/ */
@@ -76,8 +85,9 @@ public class ScriptLauncher {
} }
// Look up command in the configuration, and execute. // 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 // Destroy the service kernel if it is still alive
if (kernelImpl != null) { if (kernelImpl != null) {
@@ -86,6 +96,50 @@ public class ScriptLauncher {
} }
System.exit(status); 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) { protected static int runOneCommand(Document commandConfigs, String[] args) {
@@ -98,7 +152,7 @@ public class ScriptLauncher {
* @param commandConfigs Document * @param commandConfigs Document
* @param args the command line arguments given * @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]; String request = args[0];
Element root = commandConfigs.getRootElement(); Element root = commandConfigs.getRootElement();
List<Element> commands = root.getChildren("command"); List<Element> commands = root.getChildren("command");

View File

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

View File

@@ -7,6 +7,10 @@
*/ */
package org.dspace.content; 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.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
@@ -268,6 +272,81 @@ public class BundleServiceImpl extends DSpaceObjectServiceImpl<Bundle> implement
return authorizeService.getPolicies(context, bundle); 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 @Override
public void setOrder(Context context, Bundle bundle, UUID[] bitstreamIds) throws AuthorizeException, SQLException { public void setOrder(Context context, Bundle bundle, UUID[] bitstreamIds) throws AuthorizeException, SQLException {
authorizeService.authorizeAction(context, bundle, Constants.WRITE); 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) { public List<MetadataValue> getMetadataByMetadataString(T dso, String mdString) {
StringTokenizer dcf = new StringTokenizer(mdString, "."); StringTokenizer dcf = new StringTokenizer(mdString, ".");
String[] tokens = { "", "", "" }; String[] tokens = {"", "", ""};
int i = 0; int i = 0;
while (dcf.hasMoreTokens()) { while (dcf.hasMoreTokens()) {
tokens[i] = dcf.nextToken().trim(); tokens[i] = dcf.nextToken().trim();
@@ -250,8 +250,11 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
} }
} }
MetadataValue metadataValue = metadataValueService.create(context, dso, metadataField); MetadataValue metadataValue = metadataValueService.create(context, dso, metadataField);
//Set place to list length //Set place to list length of all metadatavalues for the given schema.element.qualifier combination.
metadataValue.setPlace(this.getMetadata(dso, Item.ANY, Item.ANY, Item.ANY, Item.ANY).size()); // 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()); metadataValue.setLanguage(lang == null ? null : lang.trim());
@@ -533,7 +536,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
protected String[] getMDValueByField(String field) { protected String[] getMDValueByField(String field) {
StringTokenizer dcf = new StringTokenizer(field, "."); StringTokenizer dcf = new StringTokenizer(field, ".");
String[] tokens = { "", "", "" }; String[] tokens = {"", "", ""};
int i = 0; int i = 0;
while (dcf.hasMoreTokens()) { while (dcf.hasMoreTokens()) {
tokens[i] = dcf.nextToken().trim(); tokens[i] = dcf.nextToken().trim();
@@ -571,7 +574,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
if (compare == 0) { if (compare == 0) {
if (o1 instanceof RelationshipMetadataValue) { if (o1 instanceof RelationshipMetadataValue) {
return 1; return 1;
} else if (o2 instanceof RelationshipMetadataValue) { } else if (o2 instanceof RelationshipMetadataValue) {
return -1; return -1;
} }
} }

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

@@ -85,8 +85,12 @@ public class RelationshipServiceImpl implements RelationshipService {
if (isRelationshipValidToCreate(context, relationship)) { if (isRelationshipValidToCreate(context, relationship)) {
if (authorizeService.authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE) || if (authorizeService.authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE) ||
authorizeService.authorizeActionBoolean(context, relationship.getRightItem(), Constants.WRITE)) { authorizeService.authorizeActionBoolean(context, relationship.getRightItem(), Constants.WRITE)) {
updatePlaceInRelationship(context, relationship, true); // This order of execution should be handled in the creation (create, updateplace, update relationship)
return relationshipDAO.create(context, relationship); // for a proper place allocation
Relationship relationshipToReturn = relationshipDAO.create(context, relationship);
updatePlaceInRelationship(context, relationshipToReturn);
update(context, relationshipToReturn);
return relationshipToReturn;
} else { } else {
throw new AuthorizeException( throw new AuthorizeException(
"You do not have write rights on this relationship's items"); "You do not have write rights on this relationship's items");
@@ -98,18 +102,34 @@ public class RelationshipServiceImpl implements RelationshipService {
} }
@Override @Override
public void updatePlaceInRelationship(Context context, Relationship relationship, boolean isCreation) public void updatePlaceInRelationship(Context context, Relationship relationship)
throws SQLException, AuthorizeException { throws SQLException, AuthorizeException {
Item leftItem = relationship.getLeftItem(); 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, List<Relationship> leftRelationships = findByItemAndRelationshipType(context,
leftItem, leftItem,
relationship.getRelationshipType(), true); relationship.getRelationshipType(), true);
Item rightItem = relationship.getRightItem();
List<Relationship> rightRelationships = findByItemAndRelationshipType(context, List<Relationship> rightRelationships = findByItemAndRelationshipType(context,
rightItem, rightItem,
relationship.getRelationshipType(), relationship.getRelationshipType(),
false); 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(); context.turnOffAuthorisationSystem();
//If useForPlace for the leftwardType is false for the relationshipType, //If useForPlace for the leftwardType is false for the relationshipType,
// we need to sort the relationships here based on leftplace. // we need to sort the relationships here based on leftplace.
@@ -145,10 +165,6 @@ public class RelationshipServiceImpl implements RelationshipService {
updateItem(context, rightItem); updateItem(context, rightItem);
} }
if (isCreation) {
handleCreationPlaces(context, relationship);
}
context.restoreAuthSystemState(); context.restoreAuthSystemState();
} }
@@ -160,43 +176,14 @@ public class RelationshipServiceImpl implements RelationshipService {
itemService.update(context, relatedItem); itemService.update(context, relatedItem);
} }
@Override
//Sets the places for the Relationship properly if the updatePlaceInRelationship was called for a new creation public int findNextLeftPlaceByLeftItem(Context context, Item item) throws SQLException {
//of this Relationship return relationshipDAO.findNextLeftPlaceByLeftItem(context, item);
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 @Override
public int findLeftPlaceByLeftItem(Context context, Item item) throws SQLException { public int findNextRightPlaceByRightItem(Context context, Item item) throws SQLException {
return relationshipDAO.findLeftPlaceByLeftItem(context, item); return relationshipDAO.findNextRightPlaceByRightItem(context, item);
}
@Override
public int findRightPlaceByRightItem(Context context, Item item) throws SQLException {
return relationshipDAO.findRightPlaceByRightItem(context, item);
} }
private boolean isRelationshipValidToCreate(Context context, Relationship relationship) throws SQLException { private boolean isRelationshipValidToCreate(Context context, Relationship relationship) throws SQLException {
@@ -348,7 +335,7 @@ public class RelationshipServiceImpl implements RelationshipService {
if (authorizeService.authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE) || if (authorizeService.authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE) ||
authorizeService.authorizeActionBoolean(context, relationship.getRightItem(), Constants.WRITE)) { authorizeService.authorizeActionBoolean(context, relationship.getRightItem(), Constants.WRITE)) {
relationshipDAO.delete(context, relationship); relationshipDAO.delete(context, relationship);
updatePlaceInRelationship(context, relationship, false); updatePlaceInRelationship(context, relationship);
} else { } else {
throw new AuthorizeException( throw new AuthorizeException(
"You do not have write rights on this relationship's items"); "You do not have write rights on this relationship's items");

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

@@ -51,26 +51,26 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset) throws SQLException; List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset) throws SQLException;
/** /**
* This method returns the highest leftplace integer for all the relationships where this * This method returns the next leftplace integer to use for a relationship with this item as the leftItem
* item is the leftitem so that we can set a proper leftplace attribute on the next relationship *
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param item The item to be matched on leftItem * @param item The item to be matched on leftItem
* @return The integer for the highest leftPlace value for all the relatonship objects * @return The next integer to be used for the leftplace of a relationship with the given item
* that have the given item as leftItem * as a left item
* @throws SQLException If something goes wrong * @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 * This method returns the next rightplace integer to use for a relationship with this item as the rightItem
* item is the rightitem so that we can set a proper rightplace attribute on the next relationship *
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param item The item to be matched on rightItem * @param item The item to be matched on rightItem
* @return The integer for the highest rightPlace value for all the relatonship objects * @return The next integer to be used for the rightplace of a relationship with the given item
* that have the given item as rightItem * as a right item
* @throws SQLException If something goes wrong * @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. * This method returns a list of Relationship objects for the given RelationshipType object.
@@ -113,7 +113,7 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
List<Relationship> findByItemAndRelationshipType(Context context, Item item, RelationshipType relationshipType, List<Relationship> findByItemAndRelationshipType(Context context, Item item, RelationshipType relationshipType,
Integer limit, Integer offset) throws SQLException; Integer limit, Integer offset) throws SQLException;
/** /**
* This method returns a list of Relationship objects for the given RelationshipType object. * This method returns a list of Relationship objects for the given RelationshipType object.
@@ -157,7 +157,6 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
List<Relationship> findByTypeName(Context context, String typeName, Integer limit, Integer offset) List<Relationship> findByTypeName(Context context, String typeName, Integer limit, Integer offset)
throws SQLException; throws SQLException;
/** /**
* Count total number of relationships (rows in relationship table) * Count total number of relationships (rows in relationship table)
* *

View File

@@ -9,7 +9,6 @@ package org.dspace.content.dao.impl;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; 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) public List<Collection> findAll(Context context, MetadataField order, Integer limit, Integer offset)
throws SQLException { throws SQLException {
StringBuilder query = new StringBuilder(); 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()); Query hibernateQuery = createQuery(context, query.toString());
if (offset != null) { if (offset != null) {
hibernateQuery.setFirstResult(offset); hibernateQuery.setFirstResult(offset);
@@ -76,7 +84,7 @@ public class CollectionDAOImpl extends AbstractHibernateDSODAO<Collection> imple
if (limit != null) { if (limit != null) {
hibernateQuery.setMaxResults(limit); hibernateQuery.setMaxResults(limit);
} }
hibernateQuery.setParameter(order.toString(), order.getID()); hibernateQuery.setParameter("sortField", order);
return list(hibernateQuery); return list(hibernateQuery);
} }

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

@@ -61,7 +61,7 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
} }
@Override @Override
public int findLeftPlaceByLeftItem(Context context, Item item) throws SQLException { public int findNextLeftPlaceByLeftItem(Context context, Item item) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class); Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
@@ -70,25 +70,25 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> impl
List<Relationship> list = list(context, criteriaQuery, false, Relationship.class, -1, -1); List<Relationship> list = list(context, criteriaQuery, false, Relationship.class, -1, -1);
list.sort((o1, o2) -> o2.getLeftPlace() - o1.getLeftPlace()); list.sort((o1, o2) -> o2.getLeftPlace() - o1.getLeftPlace());
if (!list.isEmpty()) { if (!list.isEmpty()) {
return list.get(0).getLeftPlace(); return list.get(0).getLeftPlace() + 1;
} else { } else {
return 1; return 0;
} }
} }
@Override @Override
public int findRightPlaceByRightItem(Context context, Item item) throws SQLException { public int findNextRightPlaceByRightItem(Context context, Item item) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class); Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.select(relationshipRoot); criteriaQuery.select(relationshipRoot);
criteriaQuery.where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item)); criteriaQuery.where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item));
List<Relationship> list = list(context, criteriaQuery, false, Relationship.class, -1, -1); 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()) { if (!list.isEmpty()) {
return list.get(0).getLeftPlace(); return list.get(0).getRightPlace() + 1;
} else { } else {
return 1; return 0;
} }
} }

View File

@@ -109,6 +109,31 @@ public interface BundleService extends DSpaceObjectService<Bundle>, DSpaceObject
public List<ResourcePolicy> getBundlePolicies(Context context, Bundle bundle) throws SQLException; 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 * Changes bitstream order according to the array
* *

View File

@@ -74,26 +74,26 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
public Relationship create(Context context, Relationship relationship) throws SQLException, AuthorizeException; 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 * This method returns the next leftplace integer to use for a relationship with this item as the leftItem
* that have the given item as a left item *
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param item The item that has to be the leftItem of a relationship for it to qualify * @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 * @return The next integer to be used for the leftplace of a relationship with the given item
* that have the given item as a leftitem property * as a left item
* @throws SQLException If something goes wrong * @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 * This method returns the next rightplace integer to use for a relationship with this item as the rightItem
* that have the given item as a right item *
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param item The item that has to be the rightitem of a relationship for it to qualify * @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 * @return The next integer to be used for the rightplace of a relationship with the given item
* that have the given item as a rightitem property * as a right item
* @throws SQLException If something goes wrong * @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 * This method returns a list of Relationships for which the leftItem or rightItem is equal to the given
@@ -147,10 +147,9 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param relationship The Relationship object that will have it's place updated and that will be used * @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 * 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 * @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; throws SQLException, AuthorizeException;
/** /**

View File

@@ -13,11 +13,8 @@ import java.util.Iterator;
import java.util.UUID; import java.util.UUID;
import org.apache.commons.cli.CommandLine; 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.Options;
import org.apache.commons.cli.PosixParser; import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.Logger;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.Community; import org.dspace.content.Community;
import org.dspace.content.Item; import org.dspace.content.Item;
@@ -26,103 +23,26 @@ import org.dspace.content.service.ItemService;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.handle.factory.HandleServiceFactory; 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 * 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;
/** @Autowired
* Default constructor private IndexingService indexer;
*/
private IndexClient() { }
/** private IndexClientOptions indexClientOptions;
* 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 {
Context context = new Context(Context.Mode.READ_ONLY); @Override
context.turnOffAuthorisationSystem(); public void internalRun() throws Exception {
if (indexClientOptions == IndexClientOptions.HELP) {
String usage = "org.dspace.discovery.IndexClient [-cbhf] | [-r <handle>] | [-i <handle>] or nothing to " + printHelp();
"update/clean an existing index."; return;
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);
} }
/** Acquire from dspace-services in future */ /** Acquire from dspace-services in future */
@@ -130,28 +50,29 @@ public class IndexClient {
* new DSpace.getServiceManager().getServiceByName("org.dspace.discovery.SolrIndexer"); * new DSpace.getServiceManager().getServiceByName("org.dspace.discovery.SolrIndexer");
*/ */
IndexingService indexer = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName( if (indexClientOptions == IndexClientOptions.REMOVE) {
IndexingService.class.getName(), handler.logInfo("Removing " + commandLine.getOptionValue("r") + " from Index");
IndexingService.class indexer.unIndexContent(context, commandLine.getOptionValue("r"));
); } else if (indexClientOptions == IndexClientOptions.CLEAN) {
handler.logInfo("Cleaning Index");
if (line.hasOption("r")) { indexer.cleanIndex(false);
log.info("Removing " + line.getOptionValue("r") + " from Index"); } else if (indexClientOptions == IndexClientOptions.FORCECLEAN) {
indexer.unIndexContent(context, line.getOptionValue("r")); handler.logInfo("Cleaning Index");
} else if (line.hasOption("c")) { indexer.cleanIndex(true);
log.info("Cleaning Index"); } else if (indexClientOptions == IndexClientOptions.BUILD ||
indexer.cleanIndex(line.hasOption("f")); indexClientOptions == IndexClientOptions.BUILDANDSPELLCHECK) {
} else if (line.hasOption("b")) { handler.logInfo("(Re)building index from scratch.");
log.info("(Re)building index from scratch.");
indexer.createIndex(context); indexer.createIndex(context);
checkRebuildSpellCheck(line, indexer); if (indexClientOptions == IndexClientOptions.BUILDANDSPELLCHECK) {
} else if (line.hasOption("o")) { checkRebuildSpellCheck(commandLine, indexer);
log.info("Optimizing search core."); }
} else if (indexClientOptions == IndexClientOptions.OPTIMIZE) {
handler.logInfo("Optimizing search core.");
indexer.optimize(); indexer.optimize();
} else if (line.hasOption('s')) { } else if (indexClientOptions == IndexClientOptions.SPELLCHECK) {
checkRebuildSpellCheck(line, indexer); checkRebuildSpellCheck(commandLine, indexer);
} else if (line.hasOption('i')) { } else if (indexClientOptions == IndexClientOptions.INDEX) {
final String param = line.getOptionValue('i'); final String param = commandLine.getOptionValue('i');
UUID uuid = null; UUID uuid = null;
try { try {
uuid = UUID.fromString(param); uuid = UUID.fromString(param);
@@ -171,24 +92,55 @@ public class IndexClient {
} }
} else { } else {
dso = (IndexableObject) HandleServiceFactory.getInstance() dso = (IndexableObject) HandleServiceFactory.getInstance()
.getHandleService().resolveToObject(context, param); .getHandleService().resolveToObject(context, param);
} }
if (dso == null) { if (dso == null) {
throw new IllegalArgumentException("Cannot resolve " + param + " to a DSpace object"); 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 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; final long seconds = (System.currentTimeMillis() - startTimeMillis) / 1000;
log.info("Indexed " + count + " object" + (count > 1 ? "s" : "") + " in " + seconds + " seconds"); handler.logInfo("Indexed " + count + " object" + (count > 1 ? "s" : "") + " in " + seconds + " seconds");
} else { } else if (indexClientOptions == IndexClientOptions.UPDATE ||
log.info("Updating and Cleaning Index"); indexClientOptions == IndexClientOptions.UPDATEANDSPELLCHECK) {
indexer.cleanIndex(line.hasOption("f")); handler.logInfo("Updating and Cleaning Index");
indexer.updateIndex(context, line.hasOption("f")); indexer.cleanIndex(false);
checkRebuildSpellCheck(line, indexer); 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 line the command line options
* @param indexer the solr indexer * @param indexer the solr indexer
* @throws SearchServiceException in case of a solr exception * @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 { throws SearchServiceException, IOException {
if (line.hasOption("s")) { handler.logInfo("Rebuilding spell checker.");
log.info("Rebuilding spell checker."); indexer.buildSpellCheck();
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

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

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 --Migrate Bundle2Bitsteam
ALTER TABLE bundle2bitstream ALTER COLUMN bundle_id rename to bundle_legacy_id; 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_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 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 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 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 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 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); 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 bundle_legacy_id;
ALTER TABLE bundle2bitstream DROP COLUMN bitstream_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 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 -- Migrate item

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,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,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,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

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

View File

@@ -354,4 +354,78 @@ public class RelationshipMetadataServiceTest extends AbstractUnitTest {
assertThat(issueList.size(), equalTo(1)); assertThat(issueList.size(), equalTo(1));
assertThat(issueList.get(0).getValue(), equalTo("2")); assertThat(issueList.get(0).getValue(), equalTo("2"));
} }
@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

@@ -114,11 +114,11 @@ public class RelationshipServiceImplTest {
Item item = mock(Item.class); Item item = mock(Item.class);
// Mock DAO to return mocked left place as 0 // 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 // 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), assertEquals("TestFindLeftPlaceByLeftItem 0", relationshipDAO.findNextLeftPlaceByLeftItem(context, item),
relationshipService.findLeftPlaceByLeftItem(context, item)); relationshipService.findNextLeftPlaceByLeftItem(context, item));
} }
@Test @Test
@@ -127,11 +127,11 @@ public class RelationshipServiceImplTest {
Item item = mock(Item.class); Item item = mock(Item.class);
// Mock lower level DAO to return mocked right place as 0 // 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 // 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), assertEquals("TestFindRightPlaceByRightItem 0", relationshipDAO.findNextRightPlaceByRightItem(context, item),
relationshipService.findRightPlaceByRightItem(context, item)); relationshipService.findNextRightPlaceByRightItem(context, item));
} }
@Test @Test

View File

@@ -138,24 +138,24 @@ public class RelationshipDAOImplTest extends AbstractIntegrationTest {
} }
/** /**
* Test findLeftPlaceByLeftItem should return 0 given our test left Item itemOne. * Test findNextLeftPlaceByLeftItem should return 0 given our test left Item itemOne.
* *
* @throws Exception * @throws Exception
*/ */
@Test @Test
public void testFindLeftPlaceByLeftItem() throws Exception { public void testFindNextLeftPlaceByLeftItem() throws Exception {
assertEquals("TestLeftPlaceByLeftItem 0", 0, relationshipService.findLeftPlaceByLeftItem(context, assertEquals("TestNextLeftPlaceByLeftItem 0", 1, relationshipService.findNextLeftPlaceByLeftItem(context,
itemOne)); itemOne));
} }
/** /**
* Test findRightPlaceByRightItem should return 0 given our test right Item itemTwo. * Test findNextRightPlaceByRightItem should return 0 given our test right Item itemTwo.
* *
* @throws Exception * @throws Exception
*/ */
@Test @Test
public void testFindRightPlaceByRightItem() throws Exception { public void testFindNextRightPlaceByRightItem() throws Exception {
assertEquals("TestRightPlaceByRightItem 0", 0, relationshipService.findRightPlaceByRightItem(context, assertEquals("TestNextRightPlaceByRightItem 0", 1, relationshipService.findNextRightPlaceByRightItem(context,
itemTwo)); itemTwo));
} }
@@ -183,4 +183,4 @@ public class RelationshipDAOImplTest extends AbstractIntegrationTest {
} }
} }

View File

@@ -0,0 +1,136 @@
/**
* 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 static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.LinkedList;
import java.util.List;
import org.dspace.AbstractUnitTest;
import org.junit.Test;
public class DSpaceCommandLineParameterTest extends AbstractUnitTest {
@Test
public void constructorTest() {
String key = "-c";
String value = "test";
DSpaceCommandLineParameter dSpaceCommandLineParameter = new DSpaceCommandLineParameter(key, value);
assertThat("constructorTest 0", dSpaceCommandLineParameter.getName(), equalTo(key));
assertThat("constructorTest 1", dSpaceCommandLineParameter.getValue(), equalTo(value));
}
@Test
public void constructorTestNullValue() {
String key = "-c";
String value = null;
DSpaceCommandLineParameter dSpaceCommandLineParameter = new DSpaceCommandLineParameter(key, value);
assertThat("constructorTest 0", dSpaceCommandLineParameter.getName(), equalTo(key));
assertThat("constructorTest 1", dSpaceCommandLineParameter.getValue(), equalTo(value));
}
@Test
public void singleParameterConstructorTest() {
String parameter = "-c test";
DSpaceCommandLineParameter dSpaceCommandLineParameter = new DSpaceCommandLineParameter(parameter);
assertThat("singleParameterConstructorTest 0", dSpaceCommandLineParameter.getName(), equalTo("-c"));
assertThat("singleParameterConstructorTest 1", dSpaceCommandLineParameter.getValue(), equalTo("test"));
}
@Test
public void singleParameterConstructorTestNoValue() {
String parameter = "-c";
DSpaceCommandLineParameter dSpaceCommandLineParameter = new DSpaceCommandLineParameter(parameter);
assertThat("singleParameterConstructorTest 0", dSpaceCommandLineParameter.getName(), equalTo("-c"));
assertThat("singleParameterConstructorTest 1", dSpaceCommandLineParameter.getValue(), equalTo(null));
}
@Test
public void toStringTest() {
String key = "-c";
String value = "test";
DSpaceCommandLineParameter dSpaceCommandLineParameter = new DSpaceCommandLineParameter(key, value);
assertThat("toStringTest 0", dSpaceCommandLineParameter.getName(), equalTo(key));
assertThat("toStringTest 1", dSpaceCommandLineParameter.getValue(), equalTo(value));
assertThat("toStringTest 2", dSpaceCommandLineParameter.toString(), equalTo("-c test"));
}
@Test
public void toStringTestNullValue() {
String key = "-c";
String value = null;
DSpaceCommandLineParameter dSpaceCommandLineParameter = new DSpaceCommandLineParameter(key, value);
assertThat("toStringTest 0", dSpaceCommandLineParameter.getName(), equalTo(key));
assertThat("toStringTest 1", dSpaceCommandLineParameter.getValue(), equalTo(value));
assertThat("toStringTest 2", dSpaceCommandLineParameter.toString(), equalTo("-c"));
}
@Test
public void equalsTest() {
String key = "-c";
String value = "test";
DSpaceCommandLineParameter dSpaceCommandLineParameter = new DSpaceCommandLineParameter(key, value);
DSpaceCommandLineParameter dSpaceCommandLineParameter1 = new DSpaceCommandLineParameter(key, value);
assertThat("toStringTest 0", dSpaceCommandLineParameter.getName(), equalTo(key));
assertThat("toStringTest 1", dSpaceCommandLineParameter.getValue(), equalTo(value));
assertThat("toStringTest 0", dSpaceCommandLineParameter1.getName(), equalTo(key));
assertThat("toStringTest 1", dSpaceCommandLineParameter1.getValue(), equalTo(value));
assertTrue(dSpaceCommandLineParameter.equals(dSpaceCommandLineParameter1));
}
@Test
public void concatenateTest() {
String key = "-c";
String value = "test";
DSpaceCommandLineParameter dSpaceCommandLineParameter = new DSpaceCommandLineParameter(key, value);
DSpaceCommandLineParameter dSpaceCommandLineParameter1 = new DSpaceCommandLineParameter(key, value);
String key2 = "-r";
String value2 = "testing";
DSpaceCommandLineParameter dSpaceCommandLineParameter2 = new DSpaceCommandLineParameter(key2, value2);
String key3 = "-t";
String value3 = null;
DSpaceCommandLineParameter dSpaceCommandLineParameter3 = new DSpaceCommandLineParameter(key3, value3);
List<DSpaceCommandLineParameter> dSpaceCommandLineParameterList = new LinkedList<>();
dSpaceCommandLineParameterList.add(dSpaceCommandLineParameter);
dSpaceCommandLineParameterList.add(dSpaceCommandLineParameter1);
dSpaceCommandLineParameterList.add(dSpaceCommandLineParameter2);
dSpaceCommandLineParameterList.add(dSpaceCommandLineParameter3);
String concatenedString = DSpaceCommandLineParameter.concatenate(dSpaceCommandLineParameterList);
assertThat("concatenateTest", concatenedString, equalTo(
dSpaceCommandLineParameter.toString() + DSpaceCommandLineParameter.SEPARATOR + dSpaceCommandLineParameter1
.toString() + DSpaceCommandLineParameter.SEPARATOR + dSpaceCommandLineParameter2
.toString() + DSpaceCommandLineParameter.SEPARATOR + dSpaceCommandLineParameter3.toString()));
}
}

View File

@@ -0,0 +1,42 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.scripts.impl;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.dspace.scripts.DSpaceRunnable;
public class MockDSpaceRunnableScript extends DSpaceRunnable {
private MockDSpaceRunnableScript() {
Options options = constructOptions();
this.options = options;
}
@Override
public void internalRun() throws Exception {
}
@Override
public void setup() throws ParseException {
if (!commandLine.hasOption("i")) {
throw new ParseException("-i is a mandatory parameter");
}
}
private Options constructOptions() {
Options options = new Options();
options.addOption("r", "remove", true, "description r");
options.getOption("r").setType(String.class);
options.addOption("i", "index", true, "description i");
options.getOption("i").setType(boolean.class);
options.getOption("i").setRequired(true);
return options;
}
}

View File

@@ -11,6 +11,7 @@ import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.converter.EPersonConverter; import org.dspace.app.rest.converter.EPersonConverter;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.AuthenticationStatusRest; import org.dspace.app.rest.model.AuthenticationStatusRest;
@@ -18,6 +19,7 @@ import org.dspace.app.rest.model.AuthnRest;
import org.dspace.app.rest.model.EPersonRest; import org.dspace.app.rest.model.EPersonRest;
import org.dspace.app.rest.model.hateoas.AuthenticationStatusResource; import org.dspace.app.rest.model.hateoas.AuthenticationStatusResource;
import org.dspace.app.rest.model.hateoas.AuthnResource; import org.dspace.app.rest.model.hateoas.AuthnResource;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils; import org.dspace.app.rest.utils.Utils;
import org.dspace.core.Context; import org.dspace.core.Context;
@@ -49,6 +51,9 @@ public class AuthenticationRestController implements InitializingBean {
@Autowired @Autowired
DiscoverableEndpointsService discoverableEndpointsService; DiscoverableEndpointsService discoverableEndpointsService;
@Autowired
private ConverterService converter;
@Autowired @Autowired
private EPersonConverter ePersonConverter; private EPersonConverter ePersonConverter;
@@ -65,24 +70,24 @@ public class AuthenticationRestController implements InitializingBean {
} }
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
public AuthnResource authn() throws SQLException { public AuthnResource authn() {
AuthnResource authnResource = new AuthnResource(new AuthnRest(), utils); AuthnRest authnRest = new AuthnRest();
halLinkService.addLinks(authnResource); authnRest.setProjection(utils.obtainProjection());
return authnResource; return converter.toResource(authnRest);
} }
@RequestMapping(value = "/status", method = RequestMethod.GET) @RequestMapping(value = "/status", method = RequestMethod.GET)
public AuthenticationStatusResource status(HttpServletRequest request) throws SQLException { public AuthenticationStatusResource status(HttpServletRequest request) throws SQLException {
Context context = ContextUtil.obtainContext(request); Context context = ContextUtil.obtainContext(request);
EPersonRest ePersonRest = null; EPersonRest ePersonRest = null;
Projection projection = utils.obtainProjection();
if (context.getCurrentUser() != null) { if (context.getCurrentUser() != null) {
ePersonRest = ePersonConverter.fromModelWithGroups(context, context.getCurrentUser()); ePersonRest = ePersonConverter.fromModelWithGroups(context, context.getCurrentUser(), projection);
} }
AuthenticationStatusResource authenticationStatusResource = new AuthenticationStatusResource( AuthenticationStatusRest authenticationStatusRest = new AuthenticationStatusRest(ePersonRest);
new AuthenticationStatusRest(ePersonRest), utils); authenticationStatusRest.setProjection(projection);
AuthenticationStatusResource authenticationStatusResource = converter.toResource(authenticationStatusRest);
halLinkService.addLinks(authenticationStatusResource);
return authenticationStatusResource; return authenticationStatusResource;
} }

View File

@@ -0,0 +1,153 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import static org.dspace.core.Constants.BUNDLE;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.BundleRest;
import org.dspace.app.rest.model.hateoas.BundleResource;
import org.dspace.app.rest.repository.BitstreamRestRepository;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.DSpaceObject;
import org.dspace.content.service.BitstreamService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ControllerUtils;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller to access bitstreams and the bundles they're in
* Endpoint: /api/core/bitstreams/{uuid}
* This controller can:
* - request bundle a bitstream is in (GET /api/core/bitstreams/{uuid}/bundle)
* - move bitstreams between bundles (POST /api/core/bitstreams/{uuid}/bundle (text/uri-list) -d link-to-new-bundle)
*
*/
@RestController
@RequestMapping("/api/" + BitstreamRest.CATEGORY + "/" + BitstreamRest.PLURAL_NAME
+ REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/" + BundleRest.NAME)
public class BitstreamBundleController {
@Autowired
private BitstreamService bitstreamService;
@Autowired
ConverterService converter;
@Autowired
HalLinkService halLinkService;
@Autowired
Utils utils;
@Autowired
BitstreamRestRepository bitstreamRestRepository;
/**
* This method gets the bundle of the bitstream that corresponds to to the provided bitstream uuid. When multiple
* bundles are present, only the first will be returned.
*
* @param uuid The UUID of the bitstream for which the bundle will be retrieved
* @param response The response object
* @param request The request object
* @return The wrapped resource containing the first bundle of the bitstream
* @throws IOException
* @throws SQLException
* @throws AuthorizeException
*/
@PreAuthorize("hasPermission(#uuid, 'BITSTREAM', 'READ')")
@RequestMapping(method = {RequestMethod.GET, RequestMethod.HEAD})
public ResponseEntity<ResourceSupport> getBundle(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws IOException, SQLException, AuthorizeException {
Context context = ContextUtil.obtainContext(request);
Bitstream bitstream = bitstreamService.find(context, uuid);
if (bitstream == null) {
throw new ResourceNotFoundException(
BitstreamRest.CATEGORY + "." + BitstreamRest.NAME + " with id: " + uuid + " not found");
}
List<Bundle> bundles = bitstream.getBundles();
if (bundles.isEmpty()) {
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
BundleResource bundleResource = converter.toResource(
converter.toRest(bundles.get(0), utils.obtainProjection()));
return ControllerUtils.toResponseEntity(HttpStatus.OK, null, bundleResource);
}
/**
* This method moves the bitstream to the bundle corresponding the the link provided in the body of the put request
*
* @param uuid The UUID of the bitstream for which the bundle will be retrieved
* @param response The response object
* @param request The request object
* @return The wrapped resource containing the new bundle of the bitstream
* @throws SQLException
* @throws IOException
* @throws AuthorizeException
*/
@RequestMapping(method = RequestMethod.PUT, consumes = {"text/uri-list"})
@PreAuthorize("hasPermission(#uuid, 'BITSTREAM','WRITE')")
@PostAuthorize("returnObject != null")
public BundleRest move(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, IOException, AuthorizeException {
Context context = ContextUtil.obtainContext(request);
List<DSpaceObject> dsoList = utils.constructDSpaceObjectList(context, utils.getStringListFromRequest(request));
if (dsoList.size() != 1 || dsoList.get(0).getType() != BUNDLE) {
throw new UnprocessableEntityException("No bundle has been specified " +
"or the data cannot be resolved to a bundle.");
}
Bitstream bitstream = bitstreamService.find(context, uuid);
if (bitstream == null) {
throw new ResourceNotFoundException("Bitstream with id: " + uuid + " not found");
}
BundleRest bundleRest = bitstreamRestRepository.performBitstreamMove(context, bitstream,
(Bundle) dsoList.get(0));
context.commit();
return bundleRest;
}
}

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest; package org.dspace.app.rest;
import static org.dspace.app.rest.utils.ContextUtil.obtainContext; import static org.dspace.app.rest.utils.ContextUtil.obtainContext;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import static org.springframework.web.bind.annotation.RequestMethod.PUT; import static org.springframework.web.bind.annotation.RequestMethod.PUT;
import java.io.IOException; import java.io.IOException;
@@ -22,10 +23,11 @@ import javax.ws.rs.core.Response;
import org.apache.catalina.connector.ClientAbortException; import org.apache.catalina.connector.ClientAbortException;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.converter.BitstreamConverter; import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.hateoas.BitstreamResource; import org.dspace.app.rest.model.hateoas.BitstreamResource;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.MultipartFileSender; import org.dspace.app.rest.utils.MultipartFileSender;
import org.dspace.app.rest.utils.Utils; import org.dspace.app.rest.utils.Utils;
@@ -65,7 +67,7 @@ import org.springframework.web.bind.annotation.RestController;
*/ */
@RestController @RestController
@RequestMapping("/api/" + BitstreamRest.CATEGORY + "/" + BitstreamRest.PLURAL_NAME @RequestMapping("/api/" + BitstreamRest.CATEGORY + "/" + BitstreamRest.PLURAL_NAME
+ "/{uuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}}") + REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID)
public class BitstreamRestController { public class BitstreamRestController {
private static final Logger log = org.apache.logging.log4j.LogManager private static final Logger log = org.apache.logging.log4j.LogManager
@@ -90,7 +92,7 @@ public class BitstreamRestController {
private ConfigurationService configurationService; private ConfigurationService configurationService;
@Autowired @Autowired
BitstreamConverter converter; ConverterService converter;
@Autowired @Autowired
Utils utils; Utils utils;
@@ -238,7 +240,7 @@ public class BitstreamRestController {
context.commit(); context.commit();
return (BitstreamResource) utils.getResourceRepository(BitstreamRest.CATEGORY, BitstreamRest.NAME) BitstreamRest bitstreamRest = converter.toRest(context.reloadEntity(bitstream), Projection.DEFAULT);
.wrapResource(converter.fromModel(context.reloadEntity(bitstream))); return converter.toResource(bitstreamRest);
} }
} }

View File

@@ -0,0 +1,117 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.BundleRest;
import org.dspace.app.rest.model.hateoas.BitstreamResource;
import org.dspace.app.rest.repository.BundleRestRepository;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.content.Bundle;
import org.dspace.content.service.BundleService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ControllerUtils;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* Controller to upload bitstreams to a certain bundle, indicated by a uuid in the request
* Usage: POST /api/core/bundles/{uuid}/bitstreams (with file and properties of file in request)
* Example:
* <pre>
* {@code
* curl https://<dspace.server.url>/api/core/bundles/d3599177-0408-403b-9f8d-d300edd79edb/bitstreams
* -XPOST -H 'Content-Type: multipart/form-data' \
* -H 'Authorization: Bearer eyJhbGciOiJI...' \
* -F "file=@Downloads/test.html" \
* -F 'properties={ "name": "test.html", "metadata": { "dc.description": [ { "value": "example file", "language": null,
* "authority": null, "confidence": -1, "place": 0 } ]}, "bundleName": "ORIGINAL" };type=application/json'
* }
* </pre>
*/
@RestController
@RequestMapping("/api/" + BundleRest.CATEGORY + "/" + BundleRest.PLURAL_NAME + "/"
+ REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/" + BitstreamRest.PLURAL_NAME)
public class BundleUploadBitstreamController {
private static final Logger log = LogManager.getLogger();
@Autowired
protected Utils utils;
@Autowired
private BundleService bundleService;
@Autowired
private BundleRestRepository bundleRestRepository;
@Autowired
private ConverterService converter;
/**
* Method to upload a Bitstream to a Bundle with the given UUID in the URL. This will create a Bitstream with the
* file provided in the request and attach this to the Item that matches the UUID in the URL.
* This will only work for uploading one file, any extra files will silently be ignored
*
* @return The created BitstreamResource
*/
@RequestMapping(method = RequestMethod.POST, headers = "content-type=multipart/form-data")
@PreAuthorize("hasPermission(#uuid, 'BUNDLE', 'ADD') && hasPermission(#uuid, 'BUNDLE', 'WRITE')")
public ResponseEntity<ResourceSupport> uploadBitstream(HttpServletRequest request, @PathVariable UUID uuid,
@RequestParam("file") MultipartFile uploadfile,
@RequestParam(value = "properties", required = false) String properties) {
Context context = ContextUtil.obtainContext(request);
Bundle bundle = null;
try {
bundle = bundleService.find(context, uuid);
} catch (SQLException e) {
log.error("Something went wrong trying to find the Bundle with uuid: " + uuid, e);
}
if (bundle == null) {
throw new ResourceNotFoundException("The given uuid did not resolve to a Bundle on the server: " + uuid);
}
InputStream fileInputStream = null;
try {
fileInputStream = uploadfile.getInputStream();
} catch (IOException e) {
log.error("Something went wrong when trying to read the inputstream from the given file in the request",
e);
throw new UnprocessableEntityException("The InputStream from the file couldn't be read", e);
}
BitstreamRest bitstreamRest = bundleRestRepository.uploadBitstream(
context, bundle, uploadfile.getOriginalFilename(), fileInputStream, properties);
BitstreamResource bitstreamResource = converter.toResource(bitstreamRest);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, bitstreamResource);
}
}

View File

@@ -12,6 +12,7 @@ import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.converter.HarvestedCollectionConverter; import org.dspace.app.rest.converter.HarvestedCollectionConverter;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.HarvestedCollectionRest; import org.dspace.app.rest.model.HarvestedCollectionRest;
@@ -48,6 +49,9 @@ public class CollectionHarvestSettingsController {
@Autowired @Autowired
CollectionService collectionService; CollectionService collectionService;
@Autowired
ConverterService converter;
@Autowired @Autowired
HarvestedCollectionService harvestedCollectionService; HarvestedCollectionService harvestedCollectionService;
@@ -80,9 +84,7 @@ public class CollectionHarvestSettingsController {
} }
HarvestedCollectionRest harvestedCollectionRest = harvestedCollectionRestRepository.findOne(collection); HarvestedCollectionRest harvestedCollectionRest = harvestedCollectionRestRepository.findOne(collection);
HarvestedCollectionResource resource = new HarvestedCollectionResource(harvestedCollectionRest); HarvestedCollectionResource resource = converter.toResource(harvestedCollectionRest);
halLinkService.addLinks(resource);
return resource; return resource;
} }
@@ -114,8 +116,7 @@ public class CollectionHarvestSettingsController {
// Return a harvestedCollectionResource only if a new harvestedCollection was created // Return a harvestedCollectionResource only if a new harvestedCollection was created
if (harvestedCollectionRest != null) { if (harvestedCollectionRest != null) {
harvestedCollectionResource = new HarvestedCollectionResource(harvestedCollectionRest); harvestedCollectionResource = converter.toResource(harvestedCollectionRest);
halLinkService.addLinks(harvestedCollectionResource);
} }
context.commit(); context.commit();

View File

@@ -14,6 +14,7 @@ import java.util.Objects;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.FacetConfigurationRest; import org.dspace.app.rest.model.FacetConfigurationRest;
import org.dspace.app.rest.model.FacetResultsRest; import org.dspace.app.rest.model.FacetResultsRest;
@@ -61,6 +62,9 @@ public class DiscoveryRestController implements InitializingBean {
@Autowired @Autowired
private HalLinkService halLinkService; private HalLinkService halLinkService;
@Autowired
private ConverterService converter;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
discoverableEndpointsService discoverableEndpointsService
@@ -74,8 +78,7 @@ public class DiscoveryRestController implements InitializingBean {
throws Exception { throws Exception {
SearchSupportRest searchSupportRest = discoveryRestRepository.getSearchSupport(); SearchSupportRest searchSupportRest = discoveryRestRepository.getSearchSupport();
SearchSupportResource searchSupportResource = new SearchSupportResource(searchSupportRest); SearchSupportResource searchSupportResource = converter.toResource(searchSupportRest);
halLinkService.addLinks(searchSupportResource);
return searchSupportResource; return searchSupportResource;
} }
@@ -91,9 +94,7 @@ public class DiscoveryRestController implements InitializingBean {
SearchConfigurationRest searchConfigurationRest = discoveryRestRepository SearchConfigurationRest searchConfigurationRest = discoveryRestRepository
.getSearchConfiguration(dsoScope, configuration); .getSearchConfiguration(dsoScope, configuration);
SearchConfigurationResource searchConfigurationResource = new SearchConfigurationResource( SearchConfigurationResource searchConfigurationResource = converter.toResource(searchConfigurationRest);
searchConfigurationRest);
halLinkService.addLinks(searchConfigurationResource);
return searchConfigurationResource; return searchConfigurationResource;
} }
@@ -142,9 +143,8 @@ public class DiscoveryRestController implements InitializingBean {
} }
//Get the Search results in JSON format //Get the Search results in JSON format
SearchResultsRest searchResultsRest = null; SearchResultsRest searchResultsRest = discoveryRestRepository
searchResultsRest = discoveryRestRepository .getSearchObjects(query, dsoType, dsoScope, configuration, searchFilters, page, utils.obtainProjection());
.getSearchObjects(query, dsoType, dsoScope, configuration, searchFilters, page);
//Convert the Search JSON results to paginated HAL resources //Convert the Search JSON results to paginated HAL resources
SearchResultsResource searchResultsResource = new SearchResultsResource(searchResultsRest, utils, page); SearchResultsResource searchResultsResource = new SearchResultsResource(searchResultsRest, utils, page);
@@ -164,7 +164,7 @@ public class DiscoveryRestController implements InitializingBean {
FacetConfigurationRest facetConfigurationRest = discoveryRestRepository FacetConfigurationRest facetConfigurationRest = discoveryRestRepository
.getFacetsConfiguration(dsoScope, configuration); .getFacetsConfiguration(dsoScope, configuration);
FacetConfigurationResource facetConfigurationResource = new FacetConfigurationResource(facetConfigurationRest); FacetConfigurationResource facetConfigurationResource = converter.toResource(facetConfigurationRest);
halLinkService.addLinks(facetConfigurationResource, pageable); halLinkService.addLinks(facetConfigurationResource, pageable);
return facetConfigurationResource; return facetConfigurationResource;
@@ -192,7 +192,7 @@ public class DiscoveryRestController implements InitializingBean {
FacetResultsRest facetResultsRest = discoveryRestRepository FacetResultsRest facetResultsRest = discoveryRestRepository
.getFacetObjects(facetName, prefix, query, dsoType, dsoScope, configuration, searchFilters, page); .getFacetObjects(facetName, prefix, query, dsoType, dsoScope, configuration, searchFilters, page);
FacetResultsResource facetResultsResource = new FacetResultsResource(facetResultsRest); FacetResultsResource facetResultsResource = converter.toResource(facetResultsRest);
halLinkService.addLinks(facetResultsResource, page); halLinkService.addLinks(facetResultsResource, page);
return facetResultsResource; return facetResultsResource;

View File

@@ -12,12 +12,12 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.HarvesterMetadataRest; import org.dspace.app.rest.model.HarvesterMetadataRest;
import org.dspace.app.rest.model.hateoas.HarvesterMetadataResource; import org.dspace.app.rest.model.hateoas.HarvesterMetadataResource;
import org.dspace.app.rest.utils.Utils; import org.dspace.app.rest.utils.Utils;
import org.dspace.harvest.OAIHarvester; import org.dspace.harvest.OAIHarvester;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
@@ -38,6 +38,9 @@ public class HarvesterMetadataController {
@Autowired @Autowired
private HalLinkService halLinkService; private HalLinkService halLinkService;
@Autowired
private ConverterService converter;
/** /**
* GET endpoint that returns all available metadata formats * GET endpoint that returns all available metadata formats
* @param request The request object * @param request The request object
@@ -46,15 +49,14 @@ public class HarvesterMetadataController {
*/ */
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
public HarvesterMetadataResource get(HttpServletRequest request, public HarvesterMetadataResource get(HttpServletRequest request,
HttpServletResponse response) { HttpServletResponse response) {
List<Map<String,String>> configs = OAIHarvester.getAvailableMetadataFormats(); List<Map<String,String>> configs = OAIHarvester.getAvailableMetadataFormats();
HarvesterMetadataRest data = new HarvesterMetadataRest(); HarvesterMetadataRest data = new HarvesterMetadataRest();
data.setProjection(utils.obtainProjection());
data.setConfigs(configs); data.setConfigs(configs);
HarvesterMetadataResource resource = new HarvesterMetadataResource(data, utils); HarvesterMetadataResource resource = converter.toResource(data);
halLinkService.addLinks(resource);
return resource; return resource;
} }

View File

@@ -13,15 +13,15 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.atteo.evo.inflector.English; import org.atteo.evo.inflector.English;
import org.dspace.app.rest.converter.GenericDSpaceObjectConverter; import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.model.DSpaceObjectRest; import org.dspace.app.rest.model.DSpaceObjectRest;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.identifier.IdentifierNotFoundException; import org.dspace.identifier.IdentifierNotFoundException;
@@ -53,7 +53,10 @@ public class IdentifierRestController implements InitializingBean {
Logger.getLogger(IdentifierRestController.class); Logger.getLogger(IdentifierRestController.class);
@Autowired @Autowired
private GenericDSpaceObjectConverter converter; private ConverterService converter;
@Autowired
private Utils utils;
@Autowired @Autowired
private DiscoverableEndpointsService discoverableEndpointsService; private DiscoverableEndpointsService discoverableEndpointsService;
@@ -84,7 +87,7 @@ public class IdentifierRestController implements InitializingBean {
try { try {
dso = identifierService.resolve(context, id); dso = identifierService.resolve(context, id);
if (dso != null) { if (dso != null) {
DSpaceObjectRest dsor = converter.convert(dso); DSpaceObjectRest dsor = converter.toRest(dso, utils.obtainProjection());
URI link = linkTo(dsor.getController(), dsor.getCategory(), URI link = linkTo(dsor.getController(), dsor.getCategory(),
English.plural(dsor.getType())) English.plural(dsor.getType()))
.slash(dsor.getId()).toUri(); .slash(dsor.getId()).toUri();

View File

@@ -0,0 +1,114 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import java.io.IOException;
import java.sql.SQLException;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.converter.MetadataConverter;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.BundleRest;
import org.dspace.app.rest.model.ItemRest;
import org.dspace.app.rest.model.hateoas.BundleResource;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.repository.ItemRestRepository;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bundle;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ControllerUtils;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller to add bundles to a certain item, indicated by a uuid in the request
* Usage: POST /api/core/items/<:uuid>/bundles (with name and metadata of bundle in request json)
* Example:
* <pre>
* {@code
* curl -X POST https://<dspace.server.url>/api/core/items/1911e8a4-6939-490c-b58b-a5d70f8d91fb/bundles
* -H 'Authorization: Bearer eyJhbGciOiJI...'
* -H 'Content-Type: application/json
* -d {
* "name": "ORIGINAL",
* "metadata": {...}
* }
* }
* </pre>
*/
@RestController
@RequestMapping("/api/" + ItemRest.CATEGORY + "/" + ItemRest.PLURAL_NAME + REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID
+ "/" + BundleRest.PLURAL_NAME)
public class ItemAddBundleController {
@Autowired
ConverterService converter;
@Autowired
ItemService itemService;
@Autowired
ItemRestRepository itemRestRepository;
@Autowired
MetadataConverter metadataConverter;
@Autowired
Utils utils;
/**
* Method to add a Bundle to an Item with the given UUID in the URL. This will create a Bundle with the
* name provided in the request and attach this to the Item that matches the UUID in the URL.
*
* @return The created BundleResource
*/
@RequestMapping(method = RequestMethod.POST)
@PreAuthorize("hasPermission(#uuid, 'ITEM', 'ADD')")
public ResponseEntity<ResourceSupport> addBundleToItem(@PathVariable UUID uuid,
HttpServletRequest request,
HttpServletResponse response)
throws SQLException, AuthorizeException {
Context context = ContextUtil.obtainContext(request);
Item item = itemService.find(context, uuid);
if (item == null) {
throw new ResourceNotFoundException("Could not find item with id " + uuid);
}
BundleRest bundleRest;
try {
bundleRest = new ObjectMapper().readValue(request.getInputStream(), BundleRest.class);
} catch (IOException excIO) {
throw new UnprocessableEntityException("Could not parse request body");
}
Bundle bundle = itemRestRepository.addBundleToItem(context, item, bundleRest);
BundleResource bundleResource = converter.toResource(converter.toRest(bundle, Projection.DEFAULT));
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, bundleResource);
}
}

View File

@@ -7,6 +7,7 @@
*/ */
package org.dspace.app.rest; package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import static org.dspace.core.Constants.COLLECTION; import static org.dspace.core.Constants.COLLECTION;
import java.io.IOException; import java.io.IOException;
@@ -16,10 +17,11 @@ import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.converter.CollectionConverter; import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils; import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
@@ -41,13 +43,11 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
/** /**
* This controller will handle all the incoming calls on the api/code/items/{itemUuid}/owningCollection endpoint * This controller will handle all the incoming calls on the api/code/items/{uuid}/owningCollection endpoint
* where the itemUuid corresponds to the item of which you want to edit the owning collection. * where the uuid corresponds to the item of which you want to edit the owning collection.
*/ */
@RestController @RestController
@RequestMapping("/api/core/items/" + @RequestMapping("/api/core/items" + REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/owningCollection")
"{itemUuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12" +
"}}/owningCollection")
public class ItemOwningCollectionUpdateRestController { public class ItemOwningCollectionUpdateRestController {
@Autowired @Autowired
@@ -60,7 +60,7 @@ public class ItemOwningCollectionUpdateRestController {
AuthorizeService authorizeService; AuthorizeService authorizeService;
@Autowired @Autowired
CollectionConverter converter; ConverterService converter;
@Autowired @Autowired
Utils utils; Utils utils;
@@ -69,7 +69,7 @@ public class ItemOwningCollectionUpdateRestController {
* This method will update the owning collection of the item that correspond to the provided item uuid, effectively * This method will update the owning collection of the item that correspond to the provided item uuid, effectively
* moving the item to the new collection. * moving the item to the new collection.
* *
* @param itemUuid The UUID of the item that will be moved * @param uuid The UUID of the item that will be moved
* @param response The response object * @param response The response object
* @param request The request object * @param request The request object
* @return The wrapped resource containing the new owning collection or null when the item was not moved * @return The wrapped resource containing the new owning collection or null when the item was not moved
@@ -78,9 +78,9 @@ public class ItemOwningCollectionUpdateRestController {
* @throws AuthorizeException If the user is not authorized to perform the move action * @throws AuthorizeException If the user is not authorized to perform the move action
*/ */
@RequestMapping(method = RequestMethod.PUT, consumes = {"text/uri-list"}) @RequestMapping(method = RequestMethod.PUT, consumes = {"text/uri-list"})
@PreAuthorize("hasPermission(#itemUuid, 'ITEM','WRITE')") @PreAuthorize("hasPermission(#uuid, 'ITEM','WRITE')")
@PostAuthorize("returnObject != null") @PostAuthorize("returnObject != null")
public CollectionRest move(@PathVariable UUID itemUuid, HttpServletResponse response, public CollectionRest move(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request) HttpServletRequest request)
throws SQLException, IOException, AuthorizeException { throws SQLException, IOException, AuthorizeException {
Context context = ContextUtil.obtainContext(request); Context context = ContextUtil.obtainContext(request);
@@ -92,12 +92,12 @@ public class ItemOwningCollectionUpdateRestController {
"or the data cannot be resolved to a collection."); "or the data cannot be resolved to a collection.");
} }
Collection targetCollection = performItemMove(context, itemUuid, (Collection) dsoList.get(0)); Collection targetCollection = performItemMove(context, uuid, (Collection) dsoList.get(0));
if (targetCollection == null) { if (targetCollection == null) {
return null; return null;
} }
return converter.fromModel(targetCollection); return converter.toRest(targetCollection, Projection.DEFAULT);
} }

View File

@@ -1,163 +0,0 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.converter.BitstreamConverter;
import org.dspace.app.rest.converter.MetadataConverter;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.hateoas.BitstreamResource;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat;
import org.dspace.content.Item;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/api/core/items/{uuid}")
public class ItemUploadController {
private static final Logger log = LogManager.getLogger();
@Autowired
protected Utils utils;
@Autowired
private ItemService itemService;
@Autowired
private BitstreamService bitstreamService;
@Autowired
private BitstreamConverter bitstreamConverter;
@Autowired
private MetadataConverter metadataConverter;
@Autowired
private BitstreamFormatService bitstreamFormatService;
/**
* Method to upload a Bitstream to an Item with the given UUID in the URL. This will create a Bitstream with the
* file provided in the request and attach this to the Item that matches the UUID in the URL.
* This will only work for uploading one file, any extra files will silently be ignored
* @return The created BitstreamResource
*/
@RequestMapping(method = RequestMethod.POST, value = "/bitstreams", headers = "content-type=multipart/form-data")
@PreAuthorize("hasPermission(#uuid, 'ITEM', 'WRITE') && hasPermission(#uuid, 'ITEM', 'ADD')")
public BitstreamResource uploadBitstream(HttpServletRequest request, @PathVariable UUID uuid,
@RequestParam("file") MultipartFile uploadfile,
@RequestParam(value = "properties", required = false) String properties) {
Context context = ContextUtil.obtainContext(request);
Item item = null;
Bitstream bitstream = null;
try {
item = itemService.find(context, uuid);
} catch (SQLException e) {
log.error("Something went wrong trying to find the Item with uuid: " + uuid, e);
}
if (item == null) {
throw new ResourceNotFoundException("The given uuid did not resolve to an Item on the server: " + uuid);
}
InputStream fileInputStream = null;
try {
fileInputStream = uploadfile.getInputStream();
} catch (IOException e) {
log.error("Something went wrong when trying to read the inputstream from the given file in the request",
e);
throw new UnprocessableEntityException("The InputStream from the file couldn't be read", e);
}
try {
bitstream = processBitstreamCreation(context, item, fileInputStream, properties,
uploadfile.getOriginalFilename());
itemService.update(context, item);
context.commit();
} catch (AuthorizeException | IOException | SQLException e) {
String message = "Something went wrong with trying to create the single bitstream for file with filename: "
+ uploadfile.getOriginalFilename()
+ " for item with uuid: " + uuid + " and possible properties: " + properties;
log.error(message, e);
throw new RuntimeException(message, e);
}
return new BitstreamResource(bitstreamConverter.fromModel(bitstream), utils);
}
/**
* Creates the bitstream based on the given parameters
* @param context The context
* @param item The item where the bitstream should be store
* @param fileInputStream The input stream used to create the bitstream
* @param properties The properties to be assigned to the bitstream
* @param originalFilename The filename as it was uploaded
* @return The bitstream which has been created
*/
private Bitstream processBitstreamCreation(Context context, Item item, InputStream fileInputStream,
String properties, String originalFilename)
throws AuthorizeException, IOException, SQLException {
Bitstream bitstream = null;
if (StringUtils.isNotBlank(properties)) {
ObjectMapper mapper = new ObjectMapper();
BitstreamRest bitstreamRest = null;
try {
bitstreamRest = mapper.readValue(properties, BitstreamRest.class);
} catch (Exception e) {
throw new UnprocessableEntityException("The properties parameter was incorrect: " + properties);
}
String bundleName = bitstreamRest.getBundleName();
if (StringUtils.isBlank(bundleName)) {
throw new UnprocessableEntityException("Properties without a bundleName is not allowed");
}
bitstream = itemService.createSingleBitstream(context, fileInputStream, item, bundleName);
if (bitstreamRest.getMetadata() != null) {
metadataConverter.setMetadata(context, bitstream, bitstreamRest.getMetadata());
}
String name = bitstreamRest.getName();
if (StringUtils.isNotBlank(name)) {
bitstream.setName(context, name);
} else {
bitstream.setName(context, originalFilename);
}
} else {
bitstream = itemService.createSingleBitstream(context, fileInputStream, item);
bitstream.setName(context, originalFilename);
}
BitstreamFormat bitstreamFormat = bitstreamFormatService.guessFormat(context, bitstream);
bitstreamService.setFormat(context, bitstream, bitstreamFormat);
bitstreamService.update(context, bitstream);
return bitstream;
}
}

View File

@@ -7,6 +7,7 @@
*/ */
package org.dspace.app.rest; package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import static org.dspace.core.Constants.COLLECTION; import static org.dspace.core.Constants.COLLECTION;
import java.io.IOException; import java.io.IOException;
@@ -18,7 +19,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.rest.converter.CollectionConverter; import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.exception.MethodNotAllowedException; import org.dspace.app.rest.exception.MethodNotAllowedException;
import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
@@ -46,9 +47,7 @@ import org.springframework.web.bind.annotation.RestController;
* This class will typically receive a UUID that resolves to an Item and it'll perform logic on its collections * This class will typically receive a UUID that resolves to an Item and it'll perform logic on its collections
*/ */
@RestController @RestController
@RequestMapping("/api/core/items/" + @RequestMapping("/api/core/items" + REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/mappedCollections")
"{uuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}}" +
"/mappedCollections")
public class MappedCollectionRestController { public class MappedCollectionRestController {
private static final Logger log = Logger.getLogger(MappedCollectionRestController.class); private static final Logger log = Logger.getLogger(MappedCollectionRestController.class);
@@ -57,7 +56,7 @@ public class MappedCollectionRestController {
private ItemService itemService; private ItemService itemService;
@Autowired @Autowired
private CollectionConverter collectionConverter; private ConverterService converter;
@Autowired @Autowired
private CollectionService collectionService; private CollectionService collectionService;
@@ -100,18 +99,16 @@ public class MappedCollectionRestController {
List<CollectionRest> mappingCollectionRest = new LinkedList<>(); List<CollectionRest> mappingCollectionRest = new LinkedList<>();
for (Collection collection : collections) { for (Collection collection : collections) {
if (collection.getID() != owningCollectionUuid) { if (collection.getID() != owningCollectionUuid) {
mappingCollectionRest.add(collectionConverter.fromModel(collection)); mappingCollectionRest.add(converter.toRest(collection, utils.obtainProjection()));
} }
} }
MappedCollectionRestWrapper mappingCollectionRestWrapper = new MappedCollectionRestWrapper(); MappedCollectionRestWrapper mappingCollectionRestWrapper = new MappedCollectionRestWrapper();
mappingCollectionRestWrapper.setProjection(utils.obtainProjection());
mappingCollectionRestWrapper.setMappedCollectionRestList(mappingCollectionRest); mappingCollectionRestWrapper.setMappedCollectionRestList(mappingCollectionRest);
mappingCollectionRestWrapper.setItem(item); mappingCollectionRestWrapper.setItem(item);
MappedCollectionResourceWrapper mappingCollectionResourceWrapper = new MappedCollectionResourceWrapper( MappedCollectionResourceWrapper mappingCollectionResourceWrapper =
mappingCollectionRestWrapper, utils, pageable); converter.toResource(mappingCollectionRestWrapper);
halLinkService.addLinks(mappingCollectionResourceWrapper);
return mappingCollectionResourceWrapper; return mappingCollectionResourceWrapper;

View File

@@ -7,6 +7,8 @@
*/ */
package org.dspace.app.rest; package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@@ -15,7 +17,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.rest.converter.ItemConverter; import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.model.ItemRest;
import org.dspace.app.rest.model.MappedItemRestWrapper; import org.dspace.app.rest.model.MappedItemRestWrapper;
@@ -40,8 +42,7 @@ import org.springframework.web.bind.annotation.RestController;
* have the given collection as their owning collection * have the given collection as their owning collection
*/ */
@RestController @RestController
@RequestMapping("/api/core/collections/" + @RequestMapping("/api/core/collections" + REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/mappedItems")
"{uuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}}/mappedItems")
public class MappedItemRestController { public class MappedItemRestController {
private static final Logger log = Logger.getLogger(MappedItemRestController.class); private static final Logger log = Logger.getLogger(MappedItemRestController.class);
@@ -53,7 +54,7 @@ public class MappedItemRestController {
private ItemService itemService; private ItemService itemService;
@Autowired @Autowired
private ItemConverter itemConverter; private ConverterService converter;
@Autowired @Autowired
Utils utils; Utils utils;
@@ -95,11 +96,12 @@ public class MappedItemRestController {
while (itemIterator.hasNext()) { while (itemIterator.hasNext()) {
Item item = itemIterator.next(); Item item = itemIterator.next();
if (item.getOwningCollection().getID() != uuid) { if (item.getOwningCollection().getID() != uuid) {
mappedItemRestList.add(itemConverter.fromModel(item)); mappedItemRestList.add(converter.toRest(item, utils.obtainProjection()));
} }
} }
MappedItemRestWrapper mappedItemRestWrapper = new MappedItemRestWrapper(); MappedItemRestWrapper mappedItemRestWrapper = new MappedItemRestWrapper();
mappedItemRestWrapper.setProjection(utils.obtainProjection());
mappedItemRestWrapper.setMappedItemRestList(mappedItemRestList); mappedItemRestWrapper.setMappedItemRestList(mappedItemRestList);
mappedItemRestWrapper.setCollectionUuid(uuid); mappedItemRestWrapper.setCollectionUuid(uuid);
MappedItemResourceWrapper mappedItemResourceWrapper = MappedItemResourceWrapper mappedItemResourceWrapper =

View File

@@ -7,6 +7,8 @@
*/ */
package org.dspace.app.rest; package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT;
import java.sql.SQLException; import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -29,11 +31,6 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/core/relationships") @RequestMapping("/api/core/relationships")
public class RelationshipRestController { public class RelationshipRestController {
/**
* Regular expression in the request mapping to accept number as identifier
*/
private static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT = "/{id:\\d+}";
@Autowired @Autowired
private RelationshipRestRepository relationshipRestRepository; private RelationshipRestRepository relationshipRestRepository;

View File

@@ -13,11 +13,12 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.converter.RelationshipTypeConverter; import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.RelationshipTypeRest; import org.dspace.app.rest.model.RelationshipTypeRest;
import org.dspace.app.rest.model.RelationshipTypeRestWrapper; import org.dspace.app.rest.model.RelationshipTypeRestWrapper;
import org.dspace.app.rest.model.hateoas.RelationshipTypeResourceWrapper; import org.dspace.app.rest.model.hateoas.RelationshipTypeResourceWrapper;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils; import org.dspace.app.rest.utils.Utils;
import org.dspace.content.EntityType; import org.dspace.content.EntityType;
@@ -48,7 +49,7 @@ public class RelationshipTypeRestController {
private EntityTypeService entityTypeService; private EntityTypeService entityTypeService;
@Autowired @Autowired
private RelationshipTypeConverter relationshipTypeConverter; private ConverterService converter;
@Autowired @Autowired
private Utils utils; private Utils utils;
@@ -67,7 +68,8 @@ public class RelationshipTypeRestController {
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
public RelationshipTypeResourceWrapper retrieve(@PathVariable Integer id, HttpServletResponse response, public RelationshipTypeResourceWrapper retrieve(@PathVariable Integer id,
HttpServletResponse response,
HttpServletRequest request) throws SQLException { HttpServletRequest request) throws SQLException {
Context context = ContextUtil.obtainContext(request); Context context = ContextUtil.obtainContext(request);
EntityType entityType = entityTypeService.find(context, id); EntityType entityType = entityTypeService.find(context, id);
@@ -75,19 +77,19 @@ public class RelationshipTypeRestController {
List<RelationshipTypeRest> relationshipTypeRests = new LinkedList<>(); List<RelationshipTypeRest> relationshipTypeRests = new LinkedList<>();
Projection projection = utils.obtainProjection();
for (RelationshipType relationshipType : list) { for (RelationshipType relationshipType : list) {
relationshipTypeRests.add(relationshipTypeConverter.fromModel(relationshipType)); relationshipTypeRests.add(converter.toRest(relationshipType, projection));
} }
RelationshipTypeRestWrapper relationshipTypeRestWrapper = new RelationshipTypeRestWrapper(); RelationshipTypeRestWrapper relationshipTypeRestWrapper = new RelationshipTypeRestWrapper();
relationshipTypeRestWrapper.setProjection(projection);
relationshipTypeRestWrapper.setEntityTypeId(id); relationshipTypeRestWrapper.setEntityTypeId(id);
relationshipTypeRestWrapper.setEntityTypeLabel(entityType.getLabel()); relationshipTypeRestWrapper.setEntityTypeLabel(entityType.getLabel());
relationshipTypeRestWrapper.setRelationshipTypeRestList(relationshipTypeRests); relationshipTypeRestWrapper.setRelationshipTypeRestList(relationshipTypeRests);
RelationshipTypeResourceWrapper relationshipTypeResourceWrapper = new RelationshipTypeResourceWrapper( RelationshipTypeResourceWrapper relationshipTypeResourceWrapper =
relationshipTypeRestWrapper, utils); converter.toResource(relationshipTypeRestWrapper);
halLinkService.addLinks(relationshipTypeResourceWrapper);
return relationshipTypeResourceWrapper; return relationshipTypeResourceWrapper;
} }
} }

View File

@@ -7,6 +7,9 @@
*/ */
package org.dspace.app.rest; package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
@@ -19,17 +22,16 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.atteo.evo.inflector.English; import org.atteo.evo.inflector.English;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.converter.JsonPatchConverter; import org.dspace.app.rest.converter.JsonPatchConverter;
import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.exception.PaginationException; import org.dspace.app.rest.exception.PaginationException;
@@ -64,7 +66,6 @@ import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.data.web.PagedResourcesAssembler; import org.springframework.data.web.PagedResourcesAssembler;
import org.springframework.hateoas.Link; import org.springframework.hateoas.Link;
import org.springframework.hateoas.PagedResources; import org.springframework.hateoas.PagedResources;
import org.springframework.hateoas.Resource;
import org.springframework.hateoas.ResourceSupport; import org.springframework.hateoas.ResourceSupport;
import org.springframework.hateoas.Resources; import org.springframework.hateoas.Resources;
import org.springframework.hateoas.UriTemplate; import org.springframework.hateoas.UriTemplate;
@@ -95,24 +96,6 @@ import org.springframework.web.multipart.MultipartFile;
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public class RestResourceController implements InitializingBean { public class RestResourceController implements InitializingBean {
/**
* Regular expression in the request mapping to accept UUID as identifier
*/
private static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID =
"/{uuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}}";
/**
* Regular expression in the request mapping to accept a string as identifier but not the other kind of
* identifier (digits or uuid)
*/
private static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG = "/{id:^(?!^\\d+$)" +
"(?!^[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}$)[\\w+\\-]+$+}";
/**
* Regular expression in the request mapping to accept number as identifier
*/
private static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT = "/{id:\\d+}";
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RestResourceController.class); private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RestResourceController.class);
@Autowired @Autowired
@@ -130,6 +113,9 @@ public class RestResourceController implements InitializingBean {
@Autowired @Autowired
HalLinkService linkService; HalLinkService linkService;
@Autowired
ConverterService converter;
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
List<Link> links = new ArrayList<Link>(); List<Link> links = new ArrayList<Link>();
@@ -152,22 +138,20 @@ public class RestResourceController implements InitializingBean {
* *
* Note that the regular expression in the request mapping accept a number as identifier; * Note that the regular expression in the request mapping accept a number as identifier;
* *
* Please see {@link RestResourceController#findOne(String, String, String, String)} for findOne with string as * Please see {@link RestResourceController#findOne(String, String, String)} for findOne with string as
* identifier * identifier
* and see {@link RestResourceController#findOne(String, String, UUID, String)} for uuid as identifier * and see {@link RestResourceController#findOne(String, String, UUID)} for uuid as identifier
* *
* @param apiCategory * @param apiCategory
* @param model * @param model
* @param id * @param id
* @param projection
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT) @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT)
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public DSpaceResource<RestAddressableModel> findOne(@PathVariable String apiCategory, @PathVariable String model, public DSpaceResource<RestAddressableModel> findOne(@PathVariable String apiCategory, @PathVariable String model,
@PathVariable Integer id, @PathVariable Integer id) {
@RequestParam(required = false) String projection) { return findOneInternal(apiCategory, model, id);
return findOneInternal(apiCategory, model, id, projection);
} }
/** /**
@@ -186,22 +170,20 @@ public class RestResourceController implements InitializingBean {
* </pre> * </pre>
* *
* *
* Please see {@link RestResourceController#findOne(String, String, Integer, String)} for findOne with number as * Please see {@link RestResourceController#findOne(String, String, Integer)} for findOne with number as
* identifier * identifier
* and see {@link RestResourceController#findOne(String, String, UUID, String)} for uuid as identifier * and see {@link RestResourceController#findOne(String, String, UUID)} for uuid as identifier
* *
* @param apiCategory * @param apiCategory
* @param model * @param model
* @param id * @param id
* @param projection
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG) @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG)
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public DSpaceResource<RestAddressableModel> findOne(@PathVariable String apiCategory, @PathVariable String model, public DSpaceResource<RestAddressableModel> findOne(@PathVariable String apiCategory, @PathVariable String model,
@PathVariable String id, @PathVariable String id) {
@RequestParam(required = false) String projection) { return findOneInternal(apiCategory, model, id);
return findOneInternal(apiCategory, model, id, projection);
} }
/** /**
@@ -209,22 +191,20 @@ public class RestResourceController implements InitializingBean {
* *
* Note that the regular expression in the request mapping accept a UUID as identifier; * Note that the regular expression in the request mapping accept a UUID as identifier;
* *
* Please see {@link RestResourceController#findOne(String, String, Integer, String)} for findOne with number as * Please see {@link RestResourceController#findOne(String, String, Integer)} for findOne with number as
* identifier * identifier
* and see {@link RestResourceController#findOne(String, String, String, String)} for string as identifier * and see {@link RestResourceController#findOne(String, String, String)} for string as identifier
* *
* @param apiCategory * @param apiCategory
* @param model * @param model
* @param uuid * @param uuid
* @param projection
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID) @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID)
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public DSpaceResource<RestAddressableModel> findOne(@PathVariable String apiCategory, @PathVariable String model, public DSpaceResource<RestAddressableModel> findOne(@PathVariable String apiCategory, @PathVariable String model,
@PathVariable UUID uuid, @PathVariable UUID uuid) {
@RequestParam(required = false) String projection) { return findOneInternal(apiCategory, model, uuid);
return findOneInternal(apiCategory, model, uuid, projection);
} }
/** /**
@@ -233,13 +213,10 @@ public class RestResourceController implements InitializingBean {
* @param apiCategory * @param apiCategory
* @param model * @param model
* @param id * @param id
* @param projection
* @return * @return
*/ */
private <ID extends Serializable> DSpaceResource<RestAddressableModel> findOneInternal(String apiCategory, private <ID extends Serializable> DSpaceResource<RestAddressableModel> findOneInternal(String apiCategory,
String model, ID id, String model, ID id) {
String projection) {
checkModelPluralForm(apiCategory, model);
DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model); DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model);
RestAddressableModel modelObject = null; RestAddressableModel modelObject = null;
try { try {
@@ -250,9 +227,7 @@ public class RestResourceController implements InitializingBean {
if (modelObject == null) { if (modelObject == null) {
throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found"); throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found");
} }
DSpaceResource result = repository.wrapResource(modelObject); return converter.toResource(modelObject);
linkService.addLinks(result);
return result;
} }
/** /**
@@ -267,7 +242,6 @@ public class RestResourceController implements InitializingBean {
* @param rel * @param rel
* @param page * @param page
* @param assembler * @param assembler
* @param projection
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT + "/{rel}") @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT + "/{rel}")
@@ -275,9 +249,8 @@ public class RestResourceController implements InitializingBean {
@PathVariable String apiCategory, @PathVariable String apiCategory,
@PathVariable String model, @PathVariable Integer id, @PathVariable String rel, @PathVariable String model, @PathVariable Integer id, @PathVariable String rel,
Pageable page, Pageable page,
PagedResourcesAssembler assembler, PagedResourcesAssembler assembler) {
@RequestParam(required = false) String projection) { return findRelInternal(request, response, apiCategory, model, id, rel, page, assembler);
return findRelInternal(request, response, apiCategory, model, id, rel, page, assembler, projection);
} }
/** /**
@@ -293,7 +266,6 @@ public class RestResourceController implements InitializingBean {
* @param rel * @param rel
* @param page * @param page
* @param assembler * @param assembler
* @param projection
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG + @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG +
@@ -302,9 +274,8 @@ public class RestResourceController implements InitializingBean {
@PathVariable String apiCategory, @PathVariable String apiCategory,
@PathVariable String model, @PathVariable String id, @PathVariable String rel, @PathVariable String model, @PathVariable String id, @PathVariable String rel,
Pageable page, Pageable page,
PagedResourcesAssembler assembler, PagedResourcesAssembler assembler) {
@RequestParam(required = false) String projection) { return findRelInternal(request, response, apiCategory, model, id, rel, page, assembler);
return findRelInternal(request, response, apiCategory, model, id, rel, page, assembler, projection);
} }
/** /**
@@ -319,7 +290,6 @@ public class RestResourceController implements InitializingBean {
* @param rel * @param rel
* @param page * @param page
* @param assembler * @param assembler
* @param projection
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/{rel}") @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/{rel}")
@@ -327,9 +297,8 @@ public class RestResourceController implements InitializingBean {
@PathVariable String apiCategory, @PathVariable String apiCategory,
@PathVariable String model, @PathVariable UUID uuid, @PathVariable String rel, @PathVariable String model, @PathVariable UUID uuid, @PathVariable String rel,
Pageable page, Pageable page,
PagedResourcesAssembler assembler, PagedResourcesAssembler assembler) {
@RequestParam(required = false) String projection) { return findRelInternal(request, response, apiCategory, model, uuid, rel, page, assembler);
return findRelInternal(request, response, apiCategory, model, uuid, rel, page, assembler, projection);
} }
/** /**
@@ -362,7 +331,6 @@ public class RestResourceController implements InitializingBean {
* @param relid * @param relid
* @param page * @param page
* @param assembler * @param assembler
* @param projection
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG + @RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG +
@@ -371,9 +339,8 @@ public class RestResourceController implements InitializingBean {
@PathVariable String apiCategory, @PathVariable String apiCategory,
@PathVariable String model, @PathVariable String id, @PathVariable String rel, @PathVariable String model, @PathVariable String id, @PathVariable String rel,
@PathVariable String relid, @PathVariable String relid,
Pageable page, PagedResourcesAssembler assembler, Pageable page, PagedResourcesAssembler assembler) throws Throwable {
@RequestParam(required = false) String projection) throws Throwable { return findRelEntryInternal(request, response, apiCategory, model, id, rel, relid, page, assembler);
return findRelEntryInternal(request, response, apiCategory, model, id, rel, relid, page, assembler, projection);
} }
@@ -458,8 +425,7 @@ public class RestResourceController implements InitializingBean {
if (modelObject == null) { if (modelObject == null) {
return ControllerUtils.toEmptyResponse(HttpStatus.CREATED); return ControllerUtils.toEmptyResponse(HttpStatus.CREATED);
} }
DSpaceResource result = repository.wrapResource(modelObject); DSpaceResource result = converter.toResource(modelObject);
linkService.addLinks(result);
//TODO manage HTTPHeader //TODO manage HTTPHeader
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result);
} }
@@ -491,8 +457,7 @@ public class RestResourceController implements InitializingBean {
if (modelObject == null) { if (modelObject == null) {
return ControllerUtils.toEmptyResponse(HttpStatus.CREATED); return ControllerUtils.toEmptyResponse(HttpStatus.CREATED);
} }
DSpaceResource result = repository.wrapResource(modelObject); DSpaceResource result = converter.toResource(modelObject);
linkService.addLinks(result);
//TODO manage HTTPHeader //TODO manage HTTPHeader
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result);
} }
@@ -530,8 +495,7 @@ public class RestResourceController implements InitializingBean {
} }
if (modelObject != null) { if (modelObject != null) {
DSpaceResource result = repository.wrapResource(modelObject); DSpaceResource result = converter.toResource(modelObject);
linkService.addLinks(result);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result);
} else { } else {
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT); return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
@@ -622,8 +586,7 @@ public class RestResourceController implements InitializingBean {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
return ControllerUtils.toEmptyResponse(HttpStatus.INTERNAL_SERVER_ERROR); return ControllerUtils.toEmptyResponse(HttpStatus.INTERNAL_SERVER_ERROR);
} }
DSpaceResource result = repository.wrapResource(modelObject); DSpaceResource result = converter.toResource(modelObject);
linkService.addLinks(result);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result);
} }
@@ -660,8 +623,7 @@ public class RestResourceController implements InitializingBean {
List<DSpaceResource> resources = new ArrayList<>(); List<DSpaceResource> resources = new ArrayList<>();
for (T modelObject : content) { for (T modelObject : content) {
DSpaceResource result = repository.wrapResource(modelObject); DSpaceResource result = converter.toResource(modelObject);
linkService.addLinks(result);
resources.add(result); resources.add(result);
} }
return ControllerUtils.toResponseEntity(HttpStatus.OK, null, Resources.wrap(resources)); return ControllerUtils.toResponseEntity(HttpStatus.OK, null, Resources.wrap(resources));
@@ -740,8 +702,7 @@ public class RestResourceController implements InitializingBean {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
throw e; throw e;
} }
DSpaceResource result = repository.wrapResource(modelObject); DSpaceResource result = converter.toResource(modelObject);
linkService.addLinks(result);
//TODO manage HTTPHeader //TODO manage HTTPHeader
return ControllerUtils.toResponseEntity(HttpStatus.OK, null, result); return ControllerUtils.toResponseEntity(HttpStatus.OK, null, result);
@@ -758,7 +719,6 @@ public class RestResourceController implements InitializingBean {
* @param relid * @param relid
* @param page * @param page
* @param assembler * @param assembler
* @param projection
* @return * @return
*/ */
private <ID extends Serializable> ResourceSupport findRelEntryInternal(HttpServletRequest request, private <ID extends Serializable> ResourceSupport findRelEntryInternal(HttpServletRequest request,
@@ -766,26 +726,24 @@ public class RestResourceController implements InitializingBean {
String apiCategory, String model, String apiCategory, String model,
String id, String rel, String relid, String id, String rel, String relid,
Pageable page, Pageable page,
PagedResourcesAssembler assembler, PagedResourcesAssembler assembler)
String projection) throws Throwable { throws Throwable {
checkModelPluralForm(apiCategory, model); checkModelPluralForm(apiCategory, model);
DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model); DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model);
Class<RestAddressableModel> domainClass = repository.getDomainClass(); Class<RestAddressableModel> domainClass = repository.getDomainClass();
LinkRest linkRest = utils.getLinkRest(rel, domainClass); LinkRest linkRest = utils.getClassLevelLinkRest(rel, domainClass);
if (linkRest != null) { if (linkRest != null) {
LinkRestRepository linkRepository = utils.getLinkResourceRepository(apiCategory, model, linkRest.name()); LinkRestRepository linkRepository = utils.getLinkResourceRepository(apiCategory, model, linkRest.name());
Method linkMethod = repositoryUtils.getLinkMethod("getResource", linkRepository); Method linkMethod = utils.requireMethod(linkRepository.getClass(), "getResource");
try { try {
Object object = linkMethod.invoke(linkRepository, request, id, relid, page, projection); Object object = linkMethod.invoke(linkRepository, request, id, relid, page, utils.obtainProjection());
Link link = linkTo(this.getClass(), apiCategory, model).slash(id).slash(rel).slash(relid).withSelfRel(); Link link = linkTo(this.getClass(), apiCategory, model).slash(id).slash(rel).slash(relid).withSelfRel();
List result = new ArrayList(); List result = new ArrayList();
result.add(object); result.add(object);
PageImpl<RestAddressableModel> pageResult = new PageImpl(result, page, 1); PageImpl<RestAddressableModel> pageResult = new PageImpl(result, page, 1);
Page<HALResource> halResources = pageResult.map(linkRepository::wrapResource); Page<HALResource> halResources = pageResult.map(restObject -> converter.toResource(restObject));
halResources.forEach(linkService::addLinks);
return assembler.toResource(halResources, link); return assembler.toResource(halResources, link);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
// This catch has been made to resolve the issue that caused AuthorizeDenied exceptions for the methods // This catch has been made to resolve the issue that caused AuthorizeDenied exceptions for the methods
@@ -812,63 +770,52 @@ public class RestResourceController implements InitializingBean {
* @param apiCategory * @param apiCategory
* @param model * @param model
* @param uuid * @param uuid
* @param rel
* @param page * @param page
* @param assembler * @param assembler
* @param projection
* @return * @return
*/ */
private <ID extends Serializable> ResourceSupport findRelInternal(HttpServletRequest request, private <ID extends Serializable> ResourceSupport findRelInternal(HttpServletRequest request,
HttpServletResponse response, String apiCategory, HttpServletResponse response, String apiCategory,
String model, ID uuid, String subpath, String model, ID uuid, String subpath,
Pageable page, PagedResourcesAssembler assembler, Pageable page,
String projection) { PagedResourcesAssembler assembler) {
checkModelPluralForm(apiCategory, model); checkModelPluralForm(apiCategory, model);
DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model); DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model);
Class<RestAddressableModel> domainClass = repository.getDomainClass(); Class<RestAddressableModel> domainClass = repository.getDomainClass();
LinkRest linkRest = utils.getLinkRest(subpath, domainClass); LinkRest linkRest = utils.getClassLevelLinkRest(subpath, domainClass);
PagedResources<? extends HALResource> result; PagedResources<? extends HALResource> result;
if (linkRest != null) { if (linkRest != null) {
LinkRestRepository linkRepository = utils.getLinkResourceRepository(apiCategory, model, linkRest.name()); LinkRestRepository linkRepository = utils.getLinkResourceRepository(apiCategory, model, linkRest.name());
Method linkMethod = repositoryUtils.getLinkMethod(linkRest.method(), linkRepository); Method linkMethod = utils.requireMethod(linkRepository.getClass(), linkRest.method());
try {
if (Page.class.isAssignableFrom(linkMethod.getReturnType())) {
Page<? extends RestModel> pageResult = (Page<? extends RestAddressableModel>) linkMethod
.invoke(linkRepository, request, uuid, page, utils.obtainProjection(true));
if (linkMethod == null) { Link link = null;
// TODO custom exception String querystring = request.getQueryString();
throw new RuntimeException( if (querystring != null && querystring.length() > 0) {
"Method for relation " + subpath + " not found: " + linkRest.name() + ":" + linkRest.method()); link = linkTo(this.getClass(), apiCategory, model).slash(uuid)
} else { .slash(subpath + '?' + querystring).withSelfRel();
try {
if (Page.class.isAssignableFrom(linkMethod.getReturnType())) {
Page<? extends RestModel> pageResult = (Page<? extends RestAddressableModel>) linkMethod
.invoke(linkRepository, request, uuid, page, projection);
Link link = null;
String querystring = request.getQueryString();
if (querystring != null && querystring.length() > 0) {
link = linkTo(this.getClass(), apiCategory, model).slash(uuid)
.slash(subpath + '?' + querystring).withSelfRel();
} else {
link = linkTo(this.getClass(), apiCategory, model).slash(uuid).slash(subpath).withSelfRel();
}
Page<HALResource> halResources = pageResult.map(linkRepository::wrapResource);
halResources.forEach(linkService::addLinks);
return assembler.toResource(halResources, link);
} else { } else {
RestModel object = (RestModel) linkMethod.invoke(linkRepository, request, uuid, page, link = linkTo(this.getClass(), apiCategory, model).slash(uuid).slash(subpath).withSelfRel();
projection);
Link link = linkTo(this.getClass(), apiCategory, model).slash(uuid).slash(subpath)
.withSelfRel();
HALResource tmpresult = linkRepository.wrapResource(object);
tmpresult.add(link);
return tmpresult;
} }
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e.getMessage(), e); Page<HALResource> halResources = pageResult.map(object -> converter.toResource(object));
return assembler.toResource(halResources, link);
} else {
RestModel object = (RestModel) linkMethod.invoke(linkRepository, request, uuid, page,
utils.obtainProjection());
Link link = linkTo(this.getClass(), apiCategory, model).slash(uuid).slash(subpath)
.withSelfRel();
HALResource tmpresult = converter.toResource(object);
tmpresult.add(link);
return tmpresult;
} }
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e.getMessage(), e);
} }
} }
RestAddressableModel modelObject = repository.findOne(uuid); RestAddressableModel modelObject = repository.findOne(uuid);
@@ -877,8 +824,7 @@ public class RestResourceController implements InitializingBean {
throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + uuid + " not found"); throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + uuid + " not found");
} }
DSpaceResource resource = repository.wrapResource(modelObject, subpath); DSpaceResource resource = converter.toResource(modelObject);
linkService.addLinks(resource);
String rel = null; String rel = null;
@@ -919,16 +865,7 @@ public class RestResourceController implements InitializingBean {
.getResourceRepository(fullList.get(0).getCategory(), fullList.get(0).getType()); .getResourceRepository(fullList.get(0).getCategory(), fullList.get(0).getType());
PageImpl<RestAddressableModel> pageResult = new PageImpl(fullList.subList(start, end), page, PageImpl<RestAddressableModel> pageResult = new PageImpl(fullList.subList(start, end), page,
fullList.size()); fullList.size());
result = assembler.toResource(pageResult.map(resourceRepository::wrapResource)); return assembler.toResource(pageResult.map(converter::toResource));
for (Resource subObj : result) {
if (subObj.getContent() instanceof HALResource) {
linkService.addLinks((HALResource) subObj.getContent());
}
}
return result;
} else { } else {
if (resource.getEmbeddedResources().get(rel) == null) { if (resource.getEmbeddedResources().get(rel) == null) {
response.setStatus(HttpServletResponse.SC_NO_CONTENT); response.setStatus(HttpServletResponse.SC_NO_CONTENT);
@@ -945,7 +882,6 @@ public class RestResourceController implements InitializingBean {
* @param model * @param model
* @param page * @param page
* @param assembler * @param assembler
* @param projection
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
@@ -954,18 +890,15 @@ public class RestResourceController implements InitializingBean {
@PathVariable String model, @PathVariable String model,
Pageable page, Pageable page,
PagedResourcesAssembler assembler, PagedResourcesAssembler assembler,
@RequestParam(required = false)
String projection,
HttpServletResponse response) { HttpServletResponse response) {
DSpaceRestRepository<T, ?> repository = utils.getResourceRepository(apiCategory, model); DSpaceRestRepository<T, ?> repository = utils.getResourceRepository(apiCategory, model);
Link link = linkTo(methodOn(this.getClass(), apiCategory, model).findAll(apiCategory, model, Link link = linkTo(methodOn(this.getClass(), apiCategory, model).findAll(apiCategory, model,
page, assembler, projection, response)) page, assembler, response))
.withSelfRel(); .withSelfRel();
Page<DSpaceResource<T>> resources; Page<DSpaceResource<T>> resources;
try { try {
resources = repository.findAll(page).map(repository::wrapResource); resources = repository.findAll(page).map(converter::toResource);
resources.forEach(linkService::addLinks);
} catch (PaginationException pe) { } catch (PaginationException pe) {
resources = new PageImpl<DSpaceResource<T>>(new ArrayList<DSpaceResource<T>>(), page, pe.getTotal()); resources = new PageImpl<DSpaceResource<T>>(new ArrayList<DSpaceResource<T>>(), page, pe.getTotal());
} catch (RepositoryMethodNotImplementedException mne) { } catch (RepositoryMethodNotImplementedException mne) {
@@ -1044,18 +977,15 @@ public class RestResourceController implements InitializingBean {
if (searchResult == null) { if (searchResult == null) {
resources = new PageImpl(new ArrayList(), pageable, 0); resources = new PageImpl(new ArrayList(), pageable, 0);
} else { } else {
resources = ((Page<T>) searchResult).map(repository::wrapResource); resources = ((Page<T>) searchResult).map(converter::toResource);
} }
resources.forEach(linkService::addLinks);
result = assembler.toResource(resources, link); result = assembler.toResource(resources, link);
} else { } else {
if (searchResult == null) { if (searchResult == null) {
response.setStatus(HttpServletResponse.SC_NO_CONTENT); response.setStatus(HttpServletResponse.SC_NO_CONTENT);
return null; return null;
} }
DSpaceResource<T> dsResource = repository.wrapResource((T) searchResult); return converter.toResource((T) searchResult);
linkService.addLinks(dsResource);
result = dsResource;
} }
return result; return result;
} }
@@ -1204,9 +1134,7 @@ public class RestResourceController implements InitializingBean {
if (modelObject == null) { if (modelObject == null) {
throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found"); throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found");
} }
DSpaceResource result = repository.wrapResource(modelObject); return converter.toResource(modelObject);
linkService.addLinks(result);
return result;
} }
/** /**
@@ -1229,9 +1157,6 @@ public class RestResourceController implements InitializingBean {
if (modelObject == null) { if (modelObject == null) {
throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found"); throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found");
} }
DSpaceResource result = repository.wrapResource(modelObject); return converter.toResource(modelObject);
linkService.addLinks(result);
return result;
} }
} }

View File

@@ -9,8 +9,8 @@ package org.dspace.app.rest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.RootRest;
import org.dspace.app.rest.model.hateoas.RootResource; import org.dspace.app.rest.model.hateoas.RootResource;
import org.dspace.app.rest.repository.RootRestRepository; import org.dspace.app.rest.repository.RootRestRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -39,13 +39,11 @@ public class RootRestResourceController {
@Autowired @Autowired
RootRestRepository rootRestRepository; RootRestRepository rootRestRepository;
@Autowired
ConverterService converter;
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
public RootResource listDefinedEndpoint(HttpServletRequest request) { public RootResource listDefinedEndpoint(HttpServletRequest request) {
return converter.toResource(rootRestRepository.getRoot());
RootRest rootRest = rootRestRepository.getRoot();
RootResource rootResource = new RootResource(rootRest);
halLinkService.addLinks(rootResource);
return rootResource;
} }
} }

View File

@@ -0,0 +1,62 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.model.ProcessRest;
import org.dspace.app.rest.model.ScriptRest;
import org.dspace.app.rest.model.hateoas.ProcessResource;
import org.dspace.app.rest.repository.ScriptRestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ControllerUtils;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* This controller adds additional subresource methods to allow connecting scripts with processes
*/
@RestController
@RequestMapping("/api/" + ScriptRest.CATEGORY + "/" + ScriptRest.PLURAL_NAME + "/{name}/processes")
public class ScriptProcessesController {
private static final Logger log = LogManager.getLogger();
@Autowired
private ConverterService converter;
@Autowired
private ScriptRestRepository scriptRestRepository;
/**
* This method can be called by sending a POST request to the system/scripts/{name}/processes endpoint
* This will start a process for the script that matches the given name
* @param scriptName The name of the script that we want to start a process for
* @return The ProcessResource object for the created process
* @throws Exception If something goes wrong
*/
@RequestMapping(method = RequestMethod.POST)
@PreAuthorize("hasAuthority('ADMIN')")
public ResponseEntity<ResourceSupport> startProcess(@PathVariable(name = "name") String scriptName)
throws Exception {
if (log.isTraceEnabled()) {
log.trace("Starting Process for Script with name: " + scriptName);
}
ProcessRest processRest = scriptRestRepository.startProcess(scriptName);
ProcessResource processResource = converter.toResource(processRest);
return ControllerUtils.toResponseEntity(HttpStatus.ACCEPTED, null, processResource);
}
}

View File

@@ -10,6 +10,7 @@ package org.dspace.app.rest;
import java.util.Arrays; import java.util.Arrays;
import java.util.UUID; import java.util.UUID;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException; import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.RestAddressableModel; import org.dspace.app.rest.model.RestAddressableModel;
@@ -47,6 +48,9 @@ public class StatisticsRestController implements InitializingBean {
@Autowired @Autowired
private HalLinkService halLinkService; private HalLinkService halLinkService;
@Autowired
private ConverterService converter;
@Autowired @Autowired
private StatisticsRestRepository statisticsRestRepository; private StatisticsRestRepository statisticsRestRepository;
@@ -65,12 +69,10 @@ public class StatisticsRestController implements InitializingBean {
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
public StatisticsSupportResource getStatisticsSupport() throws Exception { public StatisticsSupportResource getStatisticsSupport() throws Exception {
StatisticsSupportRest statisticsSupportRest = statisticsRestRepository.getStatisticsSupport(); StatisticsSupportRest statisticsSupportRest = statisticsRestRepository.getStatisticsSupport();
StatisticsSupportResource statisticsSupportResource = new StatisticsSupportResource(statisticsSupportRest); return converter.toResource(statisticsSupportRest);
halLinkService.addLinks(statisticsSupportResource);
return statisticsSupportResource;
} }
@RequestMapping(method = RequestMethod.GET, value = "/viewevents/{uuid}") @RequestMapping(method = RequestMethod.GET, value = "/viewevents/{uuid}")
public PagedResources<ViewEventResource> getViewEvent(@PathVariable(name = "uuid") UUID uuid) throws Exception { public PagedResources<ViewEventResource> getViewEvent(@PathVariable(name = "uuid") UUID uuid) throws Exception {
throw new RepositoryMethodNotImplementedException("No implementation found; Method not allowed!", ""); throw new RepositoryMethodNotImplementedException("No implementation found; Method not allowed!", "");
@@ -93,13 +95,13 @@ public class StatisticsRestController implements InitializingBean {
@RequestMapping(method = RequestMethod.POST, value = "/viewevents") @RequestMapping(method = RequestMethod.POST, value = "/viewevents")
public ResponseEntity<ResourceSupport> postViewEvent() throws Exception { public ResponseEntity<ResourceSupport> postViewEvent() throws Exception {
ViewEventResource result = new ViewEventResource(viewEventRestRepository.createViewEvent(), utils); ViewEventResource result = converter.toResource(viewEventRestRepository.createViewEvent());
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result);
} }
@RequestMapping(method = RequestMethod.POST, value = "/searchevents") @RequestMapping(method = RequestMethod.POST, value = "/searchevents")
public ResponseEntity<ResourceSupport> postSearchEvent() throws Exception { public ResponseEntity<ResourceSupport> postSearchEvent() throws Exception {
SearchEventResource result = new SearchEventResource(searchEventRestRepository.createSearchEvent(), utils); SearchEventResource result = converter.toResource(searchEventRestRepository.createSearchEvent());
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result);
} }

View File

@@ -14,14 +14,14 @@ import java.net.URI;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import java.util.UUID; import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.rest.converter.GenericDSpaceObjectConverter; import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.model.DSpaceObjectRest; import org.dspace.app.rest.model.DSpaceObjectRest;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.DSpaceObjectService;
@@ -57,6 +57,9 @@ public class UUIDLookupRestController implements InitializingBean {
@Autowired @Autowired
private ContentServiceFactory contentServiceFactory; private ContentServiceFactory contentServiceFactory;
@Autowired
private Utils utils;
private static final Logger log = private static final Logger log =
Logger.getLogger(UUIDLookupRestController.class); Logger.getLogger(UUIDLookupRestController.class);
@@ -64,7 +67,7 @@ public class UUIDLookupRestController implements InitializingBean {
private DiscoverableEndpointsService discoverableEndpointsService; private DiscoverableEndpointsService discoverableEndpointsService;
@Autowired @Autowired
private GenericDSpaceObjectConverter converter; private ConverterService converter;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
@@ -92,7 +95,7 @@ public class UUIDLookupRestController implements InitializingBean {
.getDSpaceObjectServices()) { .getDSpaceObjectServices()) {
DSpaceObject dso = dSpaceObjectService.find(context, uuid); DSpaceObject dso = dSpaceObjectService.find(context, uuid);
if (dso != null) { if (dso != null) {
DSpaceObjectRest dsor = converter.convert(dso); DSpaceObjectRest dsor = converter.toRest(dso, utils.obtainProjection());
URI link = linkTo(dsor.getController(), dsor.getCategory(), dsor.getTypePlural()) URI link = linkTo(dsor.getController(), dsor.getCategory(), dsor.getTypePlural())
.slash(dsor.getId()).toUri(); .slash(dsor.getId()).toUri();
response.setStatus(HttpServletResponse.SC_FOUND); response.setStatus(HttpServletResponse.SC_FOUND);

View File

@@ -17,6 +17,7 @@ import org.dspace.app.rest.model.AInprogressSubmissionRest;
import org.dspace.app.rest.model.ErrorRest; import org.dspace.app.rest.model.ErrorRest;
import org.dspace.app.rest.model.SubmissionDefinitionRest; import org.dspace.app.rest.model.SubmissionDefinitionRest;
import org.dspace.app.rest.model.SubmissionSectionRest; import org.dspace.app.rest.model.SubmissionSectionRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.submit.AbstractRestProcessingStep; import org.dspace.app.rest.submit.AbstractRestProcessingStep;
import org.dspace.app.rest.submit.SubmissionService; import org.dspace.app.rest.submit.SubmissionService;
import org.dspace.app.util.SubmissionConfigReader; import org.dspace.app.util.SubmissionConfigReader;
@@ -47,22 +48,13 @@ public abstract class AInprogressItemConverter<T extends InProgressSubmission<ID
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(AInprogressItemConverter.class); private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(AInprogressItemConverter.class);
@Autowired @Autowired
private EPersonConverter epersonConverter; private ConverterService converter;
@Autowired
private ItemConverter itemConverter;
@Autowired
private CollectionConverter collectionConverter;
protected SubmissionConfigReader submissionConfigReader;
@Autowired
private SubmissionDefinitionConverter submissionDefinitionConverter;
@Autowired @Autowired
private SubmissionSectionConverter submissionSectionConverter; private SubmissionSectionConverter submissionSectionConverter;
protected SubmissionConfigReader submissionConfigReader;
@Autowired @Autowired
SubmissionService submissionService; SubmissionService submissionService;
@@ -70,7 +62,7 @@ public abstract class AInprogressItemConverter<T extends InProgressSubmission<ID
submissionConfigReader = new SubmissionConfigReader(); submissionConfigReader = new SubmissionConfigReader();
} }
protected void fillFromModel(T obj, R witem) { protected void fillFromModel(T obj, R witem, Projection projection) {
Collection collection = obj.getCollection(); Collection collection = obj.getCollection();
Item item = obj.getItem(); Item item = obj.getItem();
EPerson submitter = null; EPerson submitter = null;
@@ -81,17 +73,17 @@ public abstract class AInprogressItemConverter<T extends InProgressSubmission<ID
} }
witem.setId(obj.getID()); witem.setId(obj.getID());
witem.setCollection(collection != null ? collectionConverter.convert(collection) : null); witem.setCollection(collection != null ? converter.toRest(collection, projection) : null);
witem.setItem(itemConverter.convert(item)); witem.setItem(converter.toRest(item, projection));
witem.setSubmitter(epersonConverter.convert(submitter)); witem.setSubmitter(converter.toRest(submitter, projection));
// 1. retrieve the submission definition // 1. retrieve the submission definition
// 2. iterate over the submission section to allow to plugin additional // 2. iterate over the submission section to allow to plugin additional
// info // info
if (collection != null) { if (collection != null) {
SubmissionDefinitionRest def = submissionDefinitionConverter SubmissionDefinitionRest def = converter.toRest(
.convert(submissionConfigReader.getSubmissionConfigByCollection(collection.getHandle())); submissionConfigReader.getSubmissionConfigByCollection(collection.getHandle()), projection);
witem.setSubmissionDefinition(def); witem.setSubmissionDefinition(def);
for (SubmissionSectionRest sections : def.getPanels()) { for (SubmissionSectionRest sections : def.getPanels()) {
SubmissionStepConfig stepConfig = submissionSectionConverter.toModel(sections); SubmissionStepConfig stepConfig = submissionSectionConverter.toModel(sections);
@@ -150,4 +142,4 @@ public abstract class AInprogressItemConverter<T extends InProgressSubmission<ID
} }
} }
} }

View File

@@ -7,8 +7,8 @@
*/ */
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.apache.commons.lang3.NotImplementedException;
import org.dspace.app.rest.model.AuthorityEntryRest; import org.dspace.app.rest.model.AuthorityEntryRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.AuthorityUtils; import org.dspace.app.rest.utils.AuthorityUtils;
import org.dspace.content.authority.Choice; import org.dspace.content.authority.Choice;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
* This is the converter from/to the Choice in the DSpace API data * This is the converter from/to the Choice in the DSpace API data
* model and the REST data model. * model and the REST data model.
* *
* TODO please do not use this convert but use the wrapper {@link AuthorityUtils#convertEntry(Choice, String)}} * TODO please do not use this convert but use the wrapper {@link AuthorityUtils#convertEntry(Choice, String, String)}
* *
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it) * @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/ */
@@ -25,8 +25,9 @@ import org.springframework.stereotype.Component;
public class AuthorityEntryRestConverter implements DSpaceConverter<Choice, AuthorityEntryRest> { public class AuthorityEntryRestConverter implements DSpaceConverter<Choice, AuthorityEntryRest> {
@Override @Override
public AuthorityEntryRest fromModel(Choice choice) { public AuthorityEntryRest convert(Choice choice, Projection projection) {
AuthorityEntryRest entry = new AuthorityEntryRest(); AuthorityEntryRest entry = new AuthorityEntryRest();
entry.setProjection(projection);
entry.setValue(choice.value); entry.setValue(choice.value);
entry.setDisplay(choice.label); entry.setDisplay(choice.label);
entry.setId(choice.authority); entry.setId(choice.authority);
@@ -35,7 +36,7 @@ public class AuthorityEntryRestConverter implements DSpaceConverter<Choice, Auth
} }
@Override @Override
public Choice toModel(AuthorityEntryRest obj) { public Class<Choice> getModelClass() {
throw new NotImplementedException("Method not implemented"); return Choice.class;
} }
} }

View File

@@ -7,8 +7,8 @@
*/ */
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.apache.commons.lang3.NotImplementedException;
import org.dspace.app.rest.model.AuthorityRest; import org.dspace.app.rest.model.AuthorityRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.AuthorityUtils; import org.dspace.app.rest.utils.AuthorityUtils;
import org.dspace.content.authority.ChoiceAuthority; import org.dspace.content.authority.ChoiceAuthority;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
* model and the REST data model * model and the REST data model
* *
* TODO please do not use this convert but use the wrapper * TODO please do not use this convert but use the wrapper
* {@link AuthorityUtils#convertAuthority(ChoiceAuthority, String)} * {@link AuthorityUtils#convertAuthority(ChoiceAuthority, String, String)}
* *
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it) * @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/ */
@@ -26,8 +26,9 @@ import org.springframework.stereotype.Component;
public class AuthorityRestConverter implements DSpaceConverter<ChoiceAuthority, AuthorityRest> { public class AuthorityRestConverter implements DSpaceConverter<ChoiceAuthority, AuthorityRest> {
@Override @Override
public AuthorityRest fromModel(ChoiceAuthority step) { public AuthorityRest convert(ChoiceAuthority step, Projection projection) {
AuthorityRest authorityRest = new AuthorityRest(); AuthorityRest authorityRest = new AuthorityRest();
authorityRest.setProjection(projection);
authorityRest.setHierarchical(step.isHierarchical()); authorityRest.setHierarchical(step.isHierarchical());
authorityRest.setScrollable(step.isScrollable()); authorityRest.setScrollable(step.isScrollable());
authorityRest.setIdentifier(step.hasIdentifier()); authorityRest.setIdentifier(step.hasIdentifier());
@@ -35,7 +36,7 @@ public class AuthorityRestConverter implements DSpaceConverter<ChoiceAuthority,
} }
@Override @Override
public ChoiceAuthority toModel(AuthorityRest obj) { public Class<ChoiceAuthority> getModelClass() {
throw new NotImplementedException("Method not implemented"); return ChoiceAuthority.class;
} }
} }

View File

@@ -10,9 +10,9 @@ package org.dspace.app.rest.converter;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import org.dspace.app.rest.model.BitstreamFormatRest;
import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.CheckSumRest; import org.dspace.app.rest.model.CheckSumRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.Bundle; import org.dspace.content.Bundle;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -25,19 +25,14 @@ import org.springframework.stereotype.Component;
* @author Andrea Bollini (andrea.bollini at 4science.it) * @author Andrea Bollini (andrea.bollini at 4science.it)
*/ */
@Component @Component
public class BitstreamConverter public class BitstreamConverter extends DSpaceObjectConverter<Bitstream, BitstreamRest> {
extends DSpaceObjectConverter<org.dspace.content.Bitstream, org.dspace.app.rest.model.BitstreamRest> {
@Autowired(required = true) @Autowired
BitstreamFormatConverter bfConverter; ConverterService converter;
@Override @Override
public org.dspace.content.Bitstream toModel(org.dspace.app.rest.model.BitstreamRest obj) { public BitstreamRest convert(org.dspace.content.Bitstream obj, Projection projection) {
return super.toModel(obj); BitstreamRest b = super.convert(obj, projection);
}
@Override
public BitstreamRest fromModel(org.dspace.content.Bitstream obj) {
BitstreamRest b = super.fromModel(obj);
b.setSequenceId(obj.getSequenceID()); b.setSequenceId(obj.getSequenceID());
List<Bundle> bundles = null; List<Bundle> bundles = null;
try { try {
@@ -53,14 +48,11 @@ public class BitstreamConverter
checksum.setCheckSumAlgorithm(obj.getChecksumAlgorithm()); checksum.setCheckSumAlgorithm(obj.getChecksumAlgorithm());
checksum.setValue(obj.getChecksum()); checksum.setValue(obj.getChecksum());
b.setCheckSum(checksum); b.setCheckSum(checksum);
BitstreamFormatRest format = null;
try { try {
format = bfConverter.fromModel(obj.getFormat(null)); b.setFormat(converter.toRest(obj.getFormat(null), projection));
} catch (Exception e) { } catch (SQLException e) {
// TODO Auto-generated catch block throw new RuntimeException(e);
e.printStackTrace();
} }
b.setFormat(format);
b.setSizeBytes(obj.getSizeBytes()); b.setSizeBytes(obj.getSizeBytes());
return b; return b;
} }
@@ -71,7 +63,7 @@ public class BitstreamConverter
} }
@Override @Override
protected Class<Bitstream> getModelClass() { public Class<Bitstream> getModelClass() {
return Bitstream.class; return Bitstream.class;
} }
} }

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.BitstreamFormatRest; import org.dspace.app.rest.model.BitstreamFormatRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.BitstreamFormat; import org.dspace.content.BitstreamFormat;
import org.dspace.content.service.BitstreamFormatService; import org.dspace.content.service.BitstreamFormatService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -26,8 +27,9 @@ public class BitstreamFormatConverter implements DSpaceConverter<BitstreamFormat
BitstreamFormatService bitstreamFormatService; BitstreamFormatService bitstreamFormatService;
@Override @Override
public BitstreamFormatRest fromModel(BitstreamFormat obj) { public BitstreamFormatRest convert(BitstreamFormat obj, Projection projection) {
BitstreamFormatRest bf = new BitstreamFormatRest(); BitstreamFormatRest bf = new BitstreamFormatRest();
bf.setProjection(projection);
bf.setId(obj.getID()); bf.setId(obj.getID());
bf.setShortDescription(obj.getShortDescription()); bf.setShortDescription(obj.getShortDescription());
bf.setDescription(obj.getDescription()); bf.setDescription(obj.getDescription());
@@ -43,8 +45,7 @@ public class BitstreamFormatConverter implements DSpaceConverter<BitstreamFormat
} }
@Override @Override
public BitstreamFormat toModel(BitstreamFormatRest obj) { public Class<BitstreamFormat> getModelClass() {
// TODO Auto-generated method stub return BitstreamFormat.class;
return null;
} }
} }

View File

@@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.dspace.app.rest.model.BrowseIndexRest; import org.dspace.app.rest.model.BrowseIndexRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowseIndex;
import org.dspace.sort.SortException; import org.dspace.sort.SortException;
import org.dspace.sort.SortOption; import org.dspace.sort.SortOption;
@@ -24,9 +25,11 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
public class BrowseIndexConverter implements DSpaceConverter<BrowseIndex, BrowseIndexRest> { public class BrowseIndexConverter implements DSpaceConverter<BrowseIndex, BrowseIndexRest> {
@Override @Override
public BrowseIndexRest fromModel(BrowseIndex obj) { public BrowseIndexRest convert(BrowseIndex obj, Projection projection) {
BrowseIndexRest bir = new BrowseIndexRest(); BrowseIndexRest bir = new BrowseIndexRest();
bir.setProjection(projection);
bir.setId(obj.getName()); bir.setId(obj.getName());
bir.setOrder(obj.getDefaultOrder()); bir.setOrder(obj.getDefaultOrder());
bir.setMetadataBrowse(obj.isMetadataIndex()); bir.setMetadataBrowse(obj.isMetadataIndex());
@@ -53,7 +56,7 @@ public class BrowseIndexConverter implements DSpaceConverter<BrowseIndex, Browse
} }
@Override @Override
public BrowseIndex toModel(BrowseIndexRest obj) { public Class<BrowseIndex> getModelClass() {
return null; return BrowseIndex.class;
} }
} }

View File

@@ -0,0 +1,48 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.converter;
import java.util.stream.Collectors;
import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.BundleRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Bundle;
import org.springframework.stereotype.Component;
@Component
public class BundleConverter
extends DSpaceObjectConverter<Bundle, BundleRest> {
@Override
public BundleRest convert(Bundle bundle, Projection projection) {
BundleRest bundleRest = super.convert(bundle, projection);
bundleRest.setBitstreams(bundle.getBitstreams()
.stream()
.map(x -> (BitstreamRest) converter.toRest(x, projection))
.collect(Collectors.toList()));
if (bundle.getPrimaryBitstream() != null) {
BitstreamRest primaryBitstreamRest = converter.toRest(bundle.getPrimaryBitstream(), projection);
bundleRest.setPrimaryBitstream(primaryBitstreamRest);
}
return bundleRest;
}
@Override
protected BundleRest newInstance() {
return new BundleRest();
}
@Override
public Class<Bundle> getModelClass() {
return Bundle.class;
}
}

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.ClaimedTaskRest; import org.dspace.app.rest.model.ClaimedTaskRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.discovery.IndexableObject; import org.dspace.discovery.IndexableObject;
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
@@ -22,30 +23,27 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
public class ClaimedTaskConverter public class ClaimedTaskConverter
implements IndexableObjectConverter<ClaimedTask, org.dspace.app.rest.model.ClaimedTaskRest> { implements IndexableObjectConverter<ClaimedTask, ClaimedTaskRest> {
@Autowired @Autowired
private WorkflowItemConverter workflowItemConverter; private ConverterService converter;
@Autowired
private EPersonConverter epersonConverter;
@Override @Override
public ClaimedTaskRest fromModel(ClaimedTask obj) { public ClaimedTaskRest convert(ClaimedTask obj, Projection projection) {
ClaimedTaskRest taskRest = new ClaimedTaskRest(); ClaimedTaskRest taskRest = new ClaimedTaskRest();
taskRest.setProjection(projection);
XmlWorkflowItem witem = obj.getWorkflowItem(); XmlWorkflowItem witem = obj.getWorkflowItem();
taskRest.setId(obj.getID()); taskRest.setId(obj.getID());
taskRest.setWorkflowitem(workflowItemConverter.convert(witem)); taskRest.setWorkflowitem(converter.toRest(witem, projection));
taskRest.setAction(obj.getActionID()); taskRest.setAction(obj.getActionID());
taskRest.setStep(obj.getStepID()); taskRest.setStep(obj.getStepID());
taskRest.setOwner(epersonConverter.convert(obj.getOwner())); taskRest.setOwner(converter.toRest(obj.getOwner(), projection));
return taskRest; return taskRest;
} }
@Override @Override
public ClaimedTask toModel(ClaimedTaskRest obj) { public Class<ClaimedTask> getModelClass() {
return null; return ClaimedTask.class;
} }
@Override @Override
@@ -53,4 +51,4 @@ public class ClaimedTaskConverter
return object instanceof ClaimedTask; return object instanceof ClaimedTask;
} }
} }

View File

@@ -16,6 +16,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.ResourcePolicyRest; import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.AuthorizeService;
@@ -44,35 +45,28 @@ public class CollectionConverter
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(CollectionConverter.class); private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(CollectionConverter.class);
@Autowired @Autowired
private BitstreamConverter bitstreamConverter; private ConverterService converter;
@Autowired @Autowired
private CollectionService collectionService; private CollectionService collectionService;
@Autowired @Autowired
private RequestService requestService; private RequestService requestService;
@Autowired @Autowired
private AuthorizeService authorizeService; private AuthorizeService authorizeService;
@Autowired
private ResourcePolicyConverter resourcePolicyConverter;
@Override @Override
public org.dspace.content.Collection toModel(org.dspace.app.rest.model.CollectionRest obj) { public CollectionRest convert(org.dspace.content.Collection obj, Projection projection) {
return (org.dspace.content.Collection) super.toModel(obj); CollectionRest col = super.convert(obj, projection);
}
@Override
public CollectionRest fromModel(org.dspace.content.Collection obj) {
CollectionRest col = (CollectionRest) super.fromModel(obj);
Bitstream logo = obj.getLogo(); Bitstream logo = obj.getLogo();
if (logo != null) { if (logo != null) {
col.setLogo(bitstreamConverter.convert(logo)); col.setLogo(converter.toRest(logo, projection));
} }
col.setDefaultAccessConditions(getDefaultBitstreamPoliciesForCollection(obj.getID())); col.setDefaultAccessConditions(getDefaultBitstreamPoliciesForCollection(obj.getID(), projection));
return col; return col;
} }
private List<ResourcePolicyRest> getDefaultBitstreamPoliciesForCollection(UUID uuid) { private List<ResourcePolicyRest> getDefaultBitstreamPoliciesForCollection(UUID uuid, Projection projection) {
Context context = null; Context context = null;
Request currentRequest = requestService.getCurrentRequest(); Request currentRequest = requestService.getCurrentRequest();
@@ -95,7 +89,7 @@ public class CollectionConverter
List<ResourcePolicyRest> results = new ArrayList<ResourcePolicyRest>(); List<ResourcePolicyRest> results = new ArrayList<ResourcePolicyRest>();
for (ResourcePolicy pp : defaultCollectionPolicies) { for (ResourcePolicy pp : defaultCollectionPolicies) {
ResourcePolicyRest accessCondition = resourcePolicyConverter.convert(pp); ResourcePolicyRest accessCondition = converter.toRest(pp, projection);
if (accessCondition != null) { if (accessCondition != null) {
results.add(accessCondition); results.add(accessCondition);
} }
@@ -109,7 +103,7 @@ public class CollectionConverter
} }
@Override @Override
protected Class<org.dspace.content.Collection> getModelClass() { public Class<org.dspace.content.Collection> getModelClass() {
return org.dspace.content.Collection.class; return org.dspace.content.Collection.class;
} }

View File

@@ -12,6 +12,7 @@ import java.util.List;
import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.CommunityRest; import org.dspace.app.rest.model.CommunityRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.Community; import org.dspace.content.Community;
@@ -31,38 +32,29 @@ public class CommunityConverter
implements IndexableObjectConverter<Community, CommunityRest> { implements IndexableObjectConverter<Community, CommunityRest> {
@Autowired @Autowired
private BitstreamConverter bitstreamConverter; private ConverterService converter;
@Autowired
private CollectionConverter collectionConverter;
@Override @Override
public org.dspace.content.Community toModel(org.dspace.app.rest.model.CommunityRest obj) { public CommunityRest convert(org.dspace.content.Community obj, Projection projection) {
return (org.dspace.content.Community) super.toModel(obj); CommunityRest com = super.convert(obj, projection);
}
@Override
public CommunityRest fromModel(org.dspace.content.Community obj) {
CommunityRest com = (CommunityRest) super.fromModel(obj);
Bitstream logo = obj.getLogo(); Bitstream logo = obj.getLogo();
if (logo != null) { if (logo != null) {
com.setLogo(bitstreamConverter.convert(logo)); com.setLogo(converter.toRest(logo, projection));
} }
List<Collection> collections = obj.getCollections(); List<Collection> collections = obj.getCollections();
List<CollectionRest> collectionsRest = new ArrayList<CollectionRest>(); List<CollectionRest> collectionsRest = new ArrayList<>();
if (collections != null) { if (collections != null) {
for (Collection col : collections) { for (Collection col : collections) {
CollectionRest colrest = collectionConverter.fromModel(col); collectionsRest.add(converter.toRest(col, projection));
collectionsRest.add(colrest);
} }
} }
com.setCollections(collectionsRest); com.setCollections(collectionsRest);
List<Community> subCommunities = obj.getSubcommunities(); List<Community> subCommunities = obj.getSubcommunities();
List<CommunityRest> communityRest = new ArrayList<CommunityRest>(); List<CommunityRest> communityRest = new ArrayList<>();
if (subCommunities != null) { if (subCommunities != null) {
for (Community scom : subCommunities) { for (Community scom : subCommunities) {
CommunityRest scomrest = this.fromModel(scom); CommunityRest scomrest = this.convert(scom, projection);
communityRest.add(scomrest); communityRest.add(scomrest);
} }
} }
@@ -77,7 +69,7 @@ public class CommunityConverter
} }
@Override @Override
protected Class<org.dspace.content.Community> getModelClass() { public Class<org.dspace.content.Community> getModelClass() {
return org.dspace.content.Community.class; return org.dspace.content.Community.class;
} }

View File

@@ -0,0 +1,303 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.converter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import org.apache.log4j.Logger;
import org.dspace.app.rest.link.HalLinkFactory;
import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.RestAddressableModel;
import org.dspace.app.rest.model.RestModel;
import org.dspace.app.rest.model.hateoas.HALResource;
import org.dspace.app.rest.projection.DefaultProjection;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
/**
* Converts domain objects from the DSpace service layer to rest objects, and from rest objects to resource
* objects, applying {@link Projection}s where applicable.
*/
@Service
public class ConverterService {
private static final Logger log = Logger.getLogger(ConverterService.class);
private final Map<String, Projection> projectionMap = new HashMap<>();
private final Map<Class, DSpaceConverter> converterMap = new HashMap<>();
private final Map<Class<? extends RestModel>, Constructor> resourceConstructors = new HashMap<>();
@Autowired
private Utils utils;
@Autowired
private HalLinkService halLinkService;
@Autowired
private List<DSpaceConverter> converters;
@Autowired
private List<Projection> projections;
/**
* Converts the given model object to a rest object, using the appropriate {@link DSpaceConverter} and
* the given projection.
* <p>
* The projection's {@link Projection#transformModel(Object)} method will be automatically applied
* before conversion. If the rest object is a {@link RestModel}, the projection's
* {@link Projection#transformRest(RestModel)} method will be automatically called after conversion.
* </p>
*
* @param modelObject the model object, which may be a JPA entity any other class for which a converter exists.
* @param projection the projection to use.
* @param <M> the type of model object. A converter {@link Component} must exist that takes this as input.
* @param <R> the inferred return type.
* @return the converted object. If it's a {@link RestAddressableModel}, its
* {@link RestAddressableModel#getProjection()} will be set to the given projection.
* @throws IllegalArgumentException if there is no compatible converter.
* @throws ClassCastException if the converter's return type is not compatible with the inferred return type.
*/
public <M, R> R toRest(M modelObject, Projection projection) {
M transformedModel = projection.transformModel(modelObject);
DSpaceConverter<M, R> converter = requireConverter(modelObject.getClass());
R restObject = converter.convert(transformedModel, projection);
if (restObject instanceof RestModel) {
return (R) projection.transformRest((RestModel) restObject);
}
return restObject;
}
/**
* Converts a list of model objects to a page of rest objects using the given {@link Projection}.
*
* @param modelObjects the list of model objects.
* @param pageable the pageable.
* @param total the total number of items.
* @param projection the projection to use.
* @param <M> the model object class.
* @param <R> the rest object class.
* @return the page.
* @throws IllegalArgumentException if there is no compatible converter.
* @throws ClassCastException if the converter's return type is not compatible with the inferred return type.
*/
public <M, R> Page<R> toRestPage(List<M> modelObjects, Pageable pageable, long total, Projection projection) {
return new PageImpl<>(modelObjects, pageable, total).map((object) -> toRest(object, projection));
}
/**
* Converts a list of model objects to a page of rest objects using the given {@link Projection}.
*
* @param modelObjects the page of model objects.
* @param projection the projection to use.
* @param <M> the model object class.
* @param <R> the rest object class.
* @return the page.
* @throws IllegalArgumentException if there is no compatible converter.
* @throws ClassCastException if the converter's return type is not compatible with the inferred return type.
*/
public <M, R> Page<R> toRestPage(Page<M> modelObjects, Projection projection) {
return modelObjects.map((object) -> toRest(object, projection));
}
/**
* Gets the converter supporting the given class as input.
*
* @param sourceClass the desired converter's input type.
* @param <M> the converter's input type.
* @param <R> the converter's output type.
* @return the converter.
* @throws IllegalArgumentException if there is no such converter.
*/
<M, R> DSpaceConverter<M, R> getConverter(Class<M> sourceClass) {
return (DSpaceConverter<M, R>) requireConverter(sourceClass);
}
/**
* Converts the given rest object to a {@link HALResource} object.
* <p>
* If the rest object is a {@link RestAddressableModel}, the projection returned by
* {@link RestAddressableModel#getProjection()} will be used to determine which optional
* embeds and links will be added, and {@link Projection#transformResource(HALResource)}
* will be automatically called before returning the final, fully converted resource.
* </p><p>
* In all cases, the {@link HalLinkService} will be used immediately after the resource is constructed,
* to ensure all {@link HalLinkFactory}s have had a chance to add links as needed.
* </p>
*
* @param restObject the input rest object.
* @param <T> the return type, a subclass of {@link HALResource}.
* @return the fully converted resource, with all automatic links and embeds applied.
* @throws IllegalArgumentException if there is no compatible resource constructor.
* @throws ClassCastException if the resource type is not compatible with the inferred return type.
*/
public <T extends HALResource> T toResource(RestModel restObject) {
T halResource = getResource(restObject);
if (restObject instanceof RestAddressableModel) {
utils.embedOrLinkClassLevelRels(halResource);
halLinkService.addLinks(halResource);
Projection projection = ((RestAddressableModel) restObject).getProjection();
return projection.transformResource(halResource);
} else {
halLinkService.addLinks(halResource);
}
return halResource;
}
/**
* Gets the projection with the given name, or the default (no-op) projection if null is given.
*
* @param projectionName the projection name, or {@code null}.
* @return the projection with the given name, or {@link DefaultProjection} if {@code null} is given.
* @throws IllegalArgumentException if a name is provided and such a projection cannot be found.
*/
public Projection getProjection(@Nullable String projectionName) {
return projectionName == null ? Projection.DEFAULT : requireProjection(projectionName);
}
/**
* Creates and returns an instance of the appropriate {@link HALResource} subclass for the given rest object.
* <p>
* <b>Note:</b> Only two forms of constructor are supported for resources that can be created with this method:
* A one-argument constructor taking the wrapped {@link RestModel}, and a two-argument constructor also taking
* a {@link Utils} instance. If both are found in a candidate resource's constructor, the two-argument form
* will be used.
* </p>
*
* @param restObject the rest object to wrap.
* @param <T> the return type, a subclass of {@link HALResource}.
* @return a new resource instance of the appropriate type.
*/
private <T extends HALResource> T getResource(RestModel restObject) {
Constructor constructor = resourceConstructors.get(restObject.getClass());
if (constructor == null) {
throw new IllegalArgumentException("No constructor found to get resource class from " + restObject);
}
try {
if (constructor.getParameterCount() == 2) {
return (T) constructor.newInstance(restObject, utils);
} else {
return (T) constructor.newInstance(restObject);
}
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException) e.getTargetException();
}
throw new RuntimeException(e);
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
/**
* Gets the projection with the given name or throws an {@link IllegalArgumentException}.
*
* @param projectionName the projection name.
* @return the projection.
* @throws IllegalArgumentException if not found.
*/
private Projection requireProjection(String projectionName) {
if (!projectionMap.containsKey(projectionName)) {
throw new IllegalArgumentException("No such projection: " + projectionName);
}
return projectionMap.get(projectionName);
}
/**
* Gets the converter that supports the given source/input class or throws an {@link IllegalArgumentException}.
*
* @param sourceClass the source/input class.
* @return the converter.
* @throws IllegalArgumentException if not found.
*/
private DSpaceConverter requireConverter(Class sourceClass) {
if (converterMap.containsKey(sourceClass)) {
return converterMap.get(sourceClass);
}
for (Class converterSourceClass : converterMap.keySet()) {
if (converterSourceClass.isAssignableFrom(sourceClass)) {
return converterMap.get(converterSourceClass);
}
}
throw new IllegalArgumentException("No converter found to get rest class from " + sourceClass);
}
/**
* Populates maps of injected components and constructors to be used by this service's public methods.
*/
@PostConstruct
private void initialize() {
// put all available projections in a map keyed by name
for (Projection projection : projections) {
projectionMap.put(projection.getName(), projection);
}
projectionMap.put(Projection.DEFAULT.getName(), Projection.DEFAULT);
// put all available converters in a map keyed by model (input) class
for (DSpaceConverter converter : converters) {
converterMap.put(converter.getModelClass(), converter);
}
// scan all resource classes and look for compatible rest classes (by naming convention),
// creating a map of resource constructors keyed by rest class, for later use.
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(Resource.class));
Set<BeanDefinition> beanDefinitions = provider.findCandidateComponents(
HALResource.class.getPackage().getName().replaceAll("\\.", "/"));
for (BeanDefinition beanDefinition : beanDefinitions) {
String resourceClassName = beanDefinition.getBeanClassName();
String resourceClassSimpleName = resourceClassName.substring(resourceClassName.lastIndexOf(".") + 1);
String restClassSimpleName = resourceClassSimpleName
.replaceAll("ResourceWrapper$", "RestWrapper")
.replaceAll("Resource$", "Rest");
String restClassName = RestModel.class.getPackage().getName() + "." + restClassSimpleName;
try {
Class<? extends RestModel> restClass =
(Class<? extends RestModel>) Class.forName(restClassName);
Class<HALResource<? extends RestModel>> resourceClass =
(Class<HALResource<? extends RestModel>>) Class.forName(resourceClassName);
Constructor compatibleConstructor = null;
for (Constructor constructor : resourceClass.getDeclaredConstructors()) {
if (constructor.getParameterCount() == 2 && constructor.getParameterTypes()[1] == Utils.class) {
compatibleConstructor = constructor;
break; // found preferred constructor
} else if (constructor.getParameterCount() == 1) {
compatibleConstructor = constructor;
}
}
if (compatibleConstructor != null) {
resourceConstructors.put(restClass, compatibleConstructor);
} else {
log.warn("Skipping registration of resource class " + resourceClassName
+ "; compatible constructor not found");
}
} catch (ClassNotFoundException e) {
log.warn("Skipping registration of resource class " + resourceClassName
+ "; rest class not found: " + restClassName);
}
}
}
}

View File

@@ -7,15 +7,11 @@
*/ */
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.springframework.core.convert.converter.Converter; import org.dspace.app.rest.projection.Projection;
public interface DSpaceConverter<M, R> extends Converter<M, R> { public interface DSpaceConverter<M, R> {
@Override
public default R convert(M source) {
return fromModel(source);
}
public abstract R fromModel(M obj); R convert(M modelObject, Projection projection);
public abstract M toModel(R obj); Class<M> getModelClass();
} }

View File

@@ -7,6 +7,8 @@
*/ */
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.MetadataValueList;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -21,32 +23,22 @@ import org.springframework.beans.factory.annotation.Autowired;
public abstract class DSpaceObjectConverter<M extends DSpaceObject, R extends org.dspace.app.rest.model public abstract class DSpaceObjectConverter<M extends DSpaceObject, R extends org.dspace.app.rest.model
.DSpaceObjectRest> implements DSpaceConverter<M, R> { .DSpaceObjectRest> implements DSpaceConverter<M, R> {
@Autowired(required = true) @Autowired
private MetadataConverter metadataConverter; ConverterService converter;
@Override @Override
public R fromModel(M obj) { public R convert(M obj, Projection projection) {
R resource = newInstance(); R resource = newInstance();
resource.setProjection(projection);
resource.setHandle(obj.getHandle()); resource.setHandle(obj.getHandle());
if (obj.getID() != null) { if (obj.getID() != null) {
resource.setUuid(obj.getID().toString()); resource.setUuid(obj.getID().toString());
} }
resource.setName(obj.getName()); resource.setName(obj.getName());
resource.setMetadata(metadataConverter.convert(obj.getMetadata())); MetadataValueList metadataValues = new MetadataValueList(obj.getMetadata());
resource.setMetadata(converter.toRest(metadataValues, projection));
return resource; return resource;
} }
@Override
public M toModel(R obj) {
return null;
}
public boolean supportsModel(DSpaceObject object) {
return object != null && object.getClass().equals(getModelClass());
}
protected abstract R newInstance(); protected abstract R newInstance();
}
protected abstract Class<M> getModelClass();
}

View File

@@ -0,0 +1,39 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.ParameterValueRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.scripts.DSpaceCommandLineParameter;
import org.springframework.stereotype.Component;
/**
* This converter will convert an object of {@Link DSpaceCommandLineParameter} to an object
* of {@link ParameterValueRest}
*/
@Component
public class DSpaceRunnableParameterConverter
implements DSpaceConverter<DSpaceCommandLineParameter, ParameterValueRest> {
@Override
public ParameterValueRest convert(DSpaceCommandLineParameter dSpaceCommandLineParameter, Projection projection) {
ParameterValueRest parameterValueRest = new ParameterValueRest();
parameterValueRest.setName(dSpaceCommandLineParameter.getName());
parameterValueRest.setValue(dSpaceCommandLineParameter.getValue());
return parameterValueRest;
}
@Override
public Class<DSpaceCommandLineParameter> getModelClass() {
return DSpaceCommandLineParameter.class;
}
public DSpaceCommandLineParameter toModel(ParameterValueRest parameterValueRest) {
return new DSpaceCommandLineParameter(parameterValueRest.getName(), parameterValueRest.getValue());
}
}

View File

@@ -12,6 +12,7 @@ import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.dspace.app.rest.model.SearchConfigurationRest; import org.dspace.app.rest.model.SearchConfigurationRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.discovery.configuration.DiscoveryConfiguration; import org.dspace.discovery.configuration.DiscoveryConfiguration;
import org.dspace.discovery.configuration.DiscoverySearchFilter; import org.dspace.discovery.configuration.DiscoverySearchFilter;
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
@@ -24,9 +25,13 @@ import org.springframework.stereotype.Component;
* to the convert method. * to the convert method.
*/ */
@Component @Component
public class DiscoverConfigurationConverter { public class DiscoverConfigurationConverter
public SearchConfigurationRest convert(DiscoveryConfiguration configuration) { implements DSpaceConverter<DiscoveryConfiguration, SearchConfigurationRest> {
@Override
public SearchConfigurationRest convert(DiscoveryConfiguration configuration, Projection projection) {
SearchConfigurationRest searchConfigurationRest = new SearchConfigurationRest(); SearchConfigurationRest searchConfigurationRest = new SearchConfigurationRest();
searchConfigurationRest.setProjection(projection);
if (configuration != null) { if (configuration != null) {
addSearchFilters(searchConfigurationRest, addSearchFilters(searchConfigurationRest,
configuration.getSearchFilters(), configuration.getSidebarFacets()); configuration.getSearchFilters(), configuration.getSidebarFacets());
@@ -36,6 +41,11 @@ public class DiscoverConfigurationConverter {
return searchConfigurationRest; return searchConfigurationRest;
} }
@Override
public Class<DiscoveryConfiguration> getModelClass() {
return DiscoveryConfiguration.class;
}
private void setDefaultSortOption(DiscoveryConfiguration configuration, private void setDefaultSortOption(DiscoveryConfiguration configuration,
SearchConfigurationRest searchConfigurationRest) { SearchConfigurationRest searchConfigurationRest) {
String defaultSort = configuration.getSearchSortConfiguration().SCORE; String defaultSort = configuration.getSearchSortConfiguration().SCORE;

View File

@@ -15,6 +15,7 @@ import org.dspace.app.rest.model.SearchFacetEntryRest;
import org.dspace.app.rest.model.SearchFacetValueRest; import org.dspace.app.rest.model.SearchFacetValueRest;
import org.dspace.app.rest.model.SearchResultsRest; import org.dspace.app.rest.model.SearchResultsRest;
import org.dspace.app.rest.parameter.SearchFilter; import org.dspace.app.rest.parameter.SearchFilter;
import org.dspace.app.rest.projection.Projection;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.discovery.DiscoverResult; import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.configuration.DiscoveryConfiguration; import org.dspace.discovery.configuration.DiscoveryConfiguration;
@@ -36,19 +37,20 @@ public class DiscoverFacetResultsConverter {
public FacetResultsRest convert(Context context, String facetName, String prefix, String query, String dsoType, public FacetResultsRest convert(Context context, String facetName, String prefix, String query, String dsoType,
String dsoScope, List<SearchFilter> searchFilters, DiscoverResult searchResult, String dsoScope, List<SearchFilter> searchFilters, DiscoverResult searchResult,
DiscoveryConfiguration configuration, Pageable page) { DiscoveryConfiguration configuration, Pageable page, Projection projection) {
FacetResultsRest facetResultsRest = new FacetResultsRest(); FacetResultsRest facetResultsRest = new FacetResultsRest();
facetResultsRest.setProjection(projection);
setRequestInformation(context, facetName, prefix, query, dsoType, dsoScope, searchFilters, searchResult, setRequestInformation(context, facetName, prefix, query, dsoType, dsoScope, searchFilters, searchResult,
configuration, facetResultsRest, page); configuration, facetResultsRest, page, projection);
addToFacetResultList(facetName, searchResult, facetResultsRest, configuration, page); addToFacetResultList(facetName, searchResult, facetResultsRest, configuration, page, projection);
return facetResultsRest; return facetResultsRest;
} }
private void addToFacetResultList(String facetName, DiscoverResult searchResult, FacetResultsRest facetResultsRest, private void addToFacetResultList(String facetName, DiscoverResult searchResult, FacetResultsRest facetResultsRest,
DiscoveryConfiguration configuration, Pageable page) { DiscoveryConfiguration configuration, Pageable page, Projection projection) {
DiscoverySearchFilterFacet field = configuration.getSidebarFacet(facetName); DiscoverySearchFilterFacet field = configuration.getSidebarFacet(facetName);
List<DiscoverResult.FacetResult> facetValues = searchResult.getFacetResult(field); List<DiscoverResult.FacetResult> facetValues = searchResult.getFacetResult(field);
@@ -59,26 +61,27 @@ public class DiscoverFacetResultsConverter {
//We requested one facet value more as the page size. We must make sure to not return the extra value. //We requested one facet value more as the page size. We must make sure to not return the extra value.
break; break;
} }
SearchFacetValueRest searchFacetValueRest = buildSearchFacetValueRestFromFacetResult(value); SearchFacetValueRest searchFacetValueRest = buildSearchFacetValueRestFromFacetResult(value, projection);
facetResultsRest.addToFacetResultList(searchFacetValueRest); facetResultsRest.addToFacetResultList(searchFacetValueRest);
valueCount++; valueCount++;
} }
} }
private SearchFacetValueRest buildSearchFacetValueRestFromFacetResult(DiscoverResult.FacetResult value) { private SearchFacetValueRest buildSearchFacetValueRestFromFacetResult(DiscoverResult.FacetResult value,
return facetValueConverter.convert(value); Projection projection) {
return facetValueConverter.convert(value, projection);
} }
private void setRequestInformation(Context context, String facetName, String prefix, String query, String dsoType, private void setRequestInformation(Context context, String facetName, String prefix, String query, String dsoType,
String dsoScope, List<SearchFilter> searchFilters, DiscoverResult searchResult, String dsoScope, List<SearchFilter> searchFilters, DiscoverResult searchResult,
DiscoveryConfiguration configuration, FacetResultsRest facetResultsRest, DiscoveryConfiguration configuration, FacetResultsRest facetResultsRest,
Pageable page) { Pageable page, Projection projection) {
facetResultsRest.setQuery(query); facetResultsRest.setQuery(query);
facetResultsRest.setPrefix(prefix); facetResultsRest.setPrefix(prefix);
facetResultsRest.setScope(dsoScope); facetResultsRest.setScope(dsoScope);
facetResultsRest.setDsoType(dsoType); facetResultsRest.setDsoType(dsoType);
facetResultsRest.setFacetEntry(convertFacetEntry(facetName, searchResult, configuration, page)); facetResultsRest.setFacetEntry(convertFacetEntry(facetName, searchResult, configuration, page, projection));
facetResultsRest.setSort(SearchResultsRest.Sorting.fromPage(page)); facetResultsRest.setSort(SearchResultsRest.Sorting.fromPage(page));
@@ -91,10 +94,12 @@ public class DiscoverFacetResultsConverter {
} }
private SearchFacetEntryRest convertFacetEntry(final String facetName, final DiscoverResult searchResult, private SearchFacetEntryRest convertFacetEntry(final String facetName, final DiscoverResult searchResult,
final DiscoveryConfiguration configuration, final Pageable page) { final DiscoveryConfiguration configuration, final Pageable page,
final Projection projection) {
DiscoverySearchFilterFacet field = configuration.getSidebarFacet(facetName); DiscoverySearchFilterFacet field = configuration.getSidebarFacet(facetName);
SearchFacetEntryRest facetEntryRest = new SearchFacetEntryRest(facetName); SearchFacetEntryRest facetEntryRest = new SearchFacetEntryRest(facetName);
facetEntryRest.setProjection(projection);
List<DiscoverResult.FacetResult> facetResults = searchResult.getFacetResult(field); List<DiscoverResult.FacetResult> facetResults = searchResult.getFacetResult(field);
if (!facetResults.isEmpty()) { if (!facetResults.isEmpty()) {

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.SearchFacetValueRest; import org.dspace.app.rest.model.SearchFacetValueRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.discovery.DiscoverResult; import org.dspace.discovery.DiscoverResult;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -17,8 +18,9 @@ import org.springframework.stereotype.Component;
@Component @Component
public class DiscoverFacetValueConverter { public class DiscoverFacetValueConverter {
public SearchFacetValueRest convert(final DiscoverResult.FacetResult value) { public SearchFacetValueRest convert(final DiscoverResult.FacetResult value, final Projection projection) {
SearchFacetValueRest valueRest = new SearchFacetValueRest(); SearchFacetValueRest valueRest = new SearchFacetValueRest();
valueRest.setProjection(projection);
valueRest.setLabel(value.getDisplayedValue()); valueRest.setLabel(value.getDisplayedValue());
valueRest.setFilterValue(value.getAsFilterQuery()); valueRest.setFilterValue(value.getAsFilterQuery());
valueRest.setFilterType(value.getFilterType()); valueRest.setFilterType(value.getFilterType());

View File

@@ -16,6 +16,7 @@ import org.dspace.app.rest.model.SearchFacetEntryRest;
import org.dspace.app.rest.model.SearchFacetValueRest; import org.dspace.app.rest.model.SearchFacetValueRest;
import org.dspace.app.rest.model.SearchResultsRest; import org.dspace.app.rest.model.SearchResultsRest;
import org.dspace.app.rest.parameter.SearchFilter; import org.dspace.app.rest.parameter.SearchFilter;
import org.dspace.app.rest.projection.Projection;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.discovery.DiscoverQuery; import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.DiscoverResult; import org.dspace.discovery.DiscoverResult;
@@ -39,13 +40,15 @@ public class DiscoverFacetsConverter {
public SearchResultsRest convert(Context context, String query, String dsoType, String configurationName, public SearchResultsRest convert(Context context, String query, String dsoType, String configurationName,
String dsoScope, List<SearchFilter> searchFilters, final Pageable page, String dsoScope, List<SearchFilter> searchFilters, final Pageable page,
DiscoveryConfiguration configuration, DiscoverResult searchResult) { DiscoveryConfiguration configuration, DiscoverResult searchResult,
Projection projection) {
SearchResultsRest searchResultsRest = new SearchResultsRest(); SearchResultsRest searchResultsRest = new SearchResultsRest();
searchResultsRest.setProjection(projection);
setRequestInformation(context, query, dsoType, configurationName, dsoScope, searchFilters, page, setRequestInformation(context, query, dsoType, configurationName, dsoScope, searchFilters, page,
searchResultsRest); searchResultsRest);
addFacetValues(context, searchResult, searchResultsRest, configuration); addFacetValues(context, searchResult, searchResultsRest, configuration, projection);
return searchResultsRest; return searchResultsRest;
} }
@@ -64,13 +67,14 @@ public class DiscoverFacetsConverter {
* The DiscoveryConfiguration applied to the query * The DiscoveryConfiguration applied to the query
*/ */
public void addFacetValues(Context context, final DiscoverResult searchResult, final SearchResultsRest resultsRest, public void addFacetValues(Context context, final DiscoverResult searchResult, final SearchResultsRest resultsRest,
final DiscoveryConfiguration configuration) { final DiscoveryConfiguration configuration, final Projection projection) {
List<DiscoverySearchFilterFacet> facets = configuration.getSidebarFacets(); List<DiscoverySearchFilterFacet> facets = configuration.getSidebarFacets();
for (DiscoverySearchFilterFacet field : CollectionUtils.emptyIfNull(facets)) { for (DiscoverySearchFilterFacet field : CollectionUtils.emptyIfNull(facets)) {
List<DiscoverResult.FacetResult> facetValues = searchResult.getFacetResult(field); List<DiscoverResult.FacetResult> facetValues = searchResult.getFacetResult(field);
SearchFacetEntryRest facetEntry = new SearchFacetEntryRest(field.getIndexFieldName()); SearchFacetEntryRest facetEntry = new SearchFacetEntryRest(field.getIndexFieldName());
facetEntry.setProjection(projection);
int valueCount = 0; int valueCount = 0;
facetEntry.setHasMore(false); facetEntry.setHasMore(false);
facetEntry.setFacetLimit(field.getFacetLimit()); facetEntry.setFacetLimit(field.getFacetLimit());
@@ -84,7 +88,7 @@ public class DiscoverFacetsConverter {
// are // are
// more results available. // more results available.
if (valueCount < field.getFacetLimit()) { if (valueCount < field.getFacetLimit()) {
SearchFacetValueRest valueRest = facetValueConverter.convert(value); SearchFacetValueRest valueRest = facetValueConverter.convert(value, projection);
facetEntry.addValue(valueRest); facetEntry.addValue(valueRest);
} else { } else {

View File

@@ -18,6 +18,7 @@ import org.dspace.app.rest.model.RestAddressableModel;
import org.dspace.app.rest.model.SearchResultEntryRest; import org.dspace.app.rest.model.SearchResultEntryRest;
import org.dspace.app.rest.model.SearchResultsRest; import org.dspace.app.rest.model.SearchResultsRest;
import org.dspace.app.rest.parameter.SearchFilter; import org.dspace.app.rest.parameter.SearchFilter;
import org.dspace.app.rest.projection.Projection;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.discovery.DiscoverResult; import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.IndexableObject; import org.dspace.discovery.IndexableObject;
@@ -45,15 +46,17 @@ public class DiscoverResultConverter {
public SearchResultsRest convert(final Context context, final String query, final String dsoType, public SearchResultsRest convert(final Context context, final String query, final String dsoType,
final String configurationName, final String scope, final String configurationName, final String scope,
final List<SearchFilter> searchFilters, final Pageable page, final List<SearchFilter> searchFilters, final Pageable page,
final DiscoverResult searchResult, final DiscoveryConfiguration configuration) { final DiscoverResult searchResult, final DiscoveryConfiguration configuration,
final Projection projection) {
SearchResultsRest resultsRest = new SearchResultsRest(); SearchResultsRest resultsRest = new SearchResultsRest();
resultsRest.setProjection(projection);
setRequestInformation(context, query, dsoType, configurationName, scope, searchFilters, page, resultsRest); setRequestInformation(context, query, dsoType, configurationName, scope, searchFilters, page, resultsRest);
addSearchResults(searchResult, resultsRest); addSearchResults(searchResult, resultsRest, projection);
addFacetValues(context, searchResult, resultsRest, configuration); addFacetValues(context, searchResult, resultsRest, configuration, projection);
resultsRest.setTotalNumberOfResults(searchResult.getTotalSearchResults()); resultsRest.setTotalNumberOfResults(searchResult.getTotalSearchResults());
@@ -61,16 +64,18 @@ public class DiscoverResultConverter {
} }
private void addFacetValues(Context context, final DiscoverResult searchResult, final SearchResultsRest resultsRest, private void addFacetValues(Context context, final DiscoverResult searchResult, final SearchResultsRest resultsRest,
final DiscoveryConfiguration configuration) { final DiscoveryConfiguration configuration, final Projection projection) {
facetConverter.addFacetValues(context, searchResult, resultsRest, configuration); facetConverter.addFacetValues(context, searchResult, resultsRest, configuration, projection);
} }
private void addSearchResults(final DiscoverResult searchResult, final SearchResultsRest resultsRest) { private void addSearchResults(final DiscoverResult searchResult, final SearchResultsRest resultsRest,
final Projection projection) {
for (IndexableObject dspaceObject : CollectionUtils.emptyIfNull(searchResult.getIndexableObjects())) { for (IndexableObject dspaceObject : CollectionUtils.emptyIfNull(searchResult.getIndexableObjects())) {
SearchResultEntryRest resultEntry = new SearchResultEntryRest(); SearchResultEntryRest resultEntry = new SearchResultEntryRest();
resultEntry.setProjection(projection);
//Convert the DSpace Object to its REST model //Convert the DSpace Object to its REST model
resultEntry.setIndexableObject(convertDSpaceObject(dspaceObject)); resultEntry.setIndexableObject(convertDSpaceObject(dspaceObject, projection));
//Add hit highlighting for this DSO if present //Add hit highlighting for this DSO if present
DiscoverResult.IndexableObjectHighlightResult highlightedResults = searchResult DiscoverResult.IndexableObjectHighlightResult highlightedResults = searchResult
@@ -86,10 +91,10 @@ public class DiscoverResultConverter {
} }
} }
private RestAddressableModel convertDSpaceObject(final IndexableObject dspaceObject) { private RestAddressableModel convertDSpaceObject(final IndexableObject dspaceObject, final Projection projection) {
for (IndexableObjectConverter<IndexableObject, RestAddressableModel> converter : converters) { for (IndexableObjectConverter<IndexableObject, RestAddressableModel> converter : converters) {
if (converter.supportsModel(dspaceObject)) { if (converter.supportsModel(dspaceObject)) {
return converter.convert(dspaceObject); return converter.convert(dspaceObject, projection);
} }
} }
return null; return null;

View File

@@ -14,6 +14,7 @@ import java.util.List;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.model.EPersonRest; import org.dspace.app.rest.model.EPersonRest;
import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group; import org.dspace.eperson.Group;
@@ -30,17 +31,17 @@ import org.springframework.stereotype.Component;
@Component @Component
public class EPersonConverter extends DSpaceObjectConverter<EPerson, org.dspace.app.rest.model.EPersonRest> { public class EPersonConverter extends DSpaceObjectConverter<EPerson, org.dspace.app.rest.model.EPersonRest> {
@Autowired(required = true) @Autowired
private GroupConverter epersonGroupConverter; private ConverterService converter;
@Autowired(required = true) @Autowired
private GroupService groupService; private GroupService groupService;
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(EPersonConverter.class); private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(EPersonConverter.class);
@Override @Override
public EPersonRest fromModel(EPerson obj) { public EPersonRest convert(EPerson obj, Projection projection) {
EPersonRest eperson = super.fromModel(obj); EPersonRest eperson = super.convert(obj, projection);
eperson.setLastActive(obj.getLastActive()); eperson.setLastActive(obj.getLastActive());
eperson.setNetid(obj.getNetid()); eperson.setNetid(obj.getNetid());
eperson.setCanLogIn(obj.canLogIn()); eperson.setCanLogIn(obj.canLogIn());
@@ -51,31 +52,26 @@ public class EPersonConverter extends DSpaceObjectConverter<EPerson, org.dspace.
return eperson; return eperson;
} }
public EPersonRest fromModelWithGroups(Context context, EPerson ePerson) throws SQLException { public EPersonRest fromModelWithGroups(Context context, EPerson ePerson, Projection projection)
EPersonRest eperson = fromModel(ePerson); throws SQLException {
EPersonRest eperson = convert(ePerson, projection);
List<GroupRest> groups = new ArrayList<GroupRest>(); List<GroupRest> groups = new ArrayList<>();
for (Group g : groupService.allMemberGroups(context, ePerson)) { for (Group g : groupService.allMemberGroups(context, ePerson)) {
groups.add(epersonGroupConverter.convert(g)); groups.add(converter.toRest(g, projection));
} }
eperson.setGroups(groups); eperson.setGroups(groups);
return eperson; return eperson;
} }
@Override
public EPerson toModel(EPersonRest obj) {
// TODO Auto-generated method stub
return null;
}
@Override @Override
protected EPersonRest newInstance() { protected EPersonRest newInstance() {
return new EPersonRest(); return new EPersonRest();
} }
@Override @Override
protected Class<EPerson> getModelClass() { public Class<EPerson> getModelClass() {
return EPerson.class; return EPerson.class;
} }

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.EntityTypeRest; import org.dspace.app.rest.model.EntityTypeRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.EntityType; import org.dspace.content.EntityType;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -18,29 +19,17 @@ import org.springframework.stereotype.Component;
@Component @Component
public class EntityTypeConverter implements DSpaceConverter<org.dspace.content.EntityType, EntityTypeRest> { public class EntityTypeConverter implements DSpaceConverter<org.dspace.content.EntityType, EntityTypeRest> {
/** @Override
* This method converts the EntityType model object that is passed along in the params to the public EntityTypeRest convert(EntityType obj, Projection projection) {
* REST representation of this object
* @param obj The EntityType model object to be converted
* @return The EntityType REST object that is made from the model object
*/
public EntityTypeRest fromModel(EntityType obj) {
EntityTypeRest entityTypeRest = new EntityTypeRest(); EntityTypeRest entityTypeRest = new EntityTypeRest();
entityTypeRest.setProjection(projection);
entityTypeRest.setId(obj.getID()); entityTypeRest.setId(obj.getID());
entityTypeRest.setLabel(obj.getLabel()); entityTypeRest.setLabel(obj.getLabel());
return entityTypeRest; return entityTypeRest;
} }
/** @Override
* This method converts the EntityType REST object that is passed along in the params to the model public Class<EntityType> getModelClass() {
* representation of this object return EntityType.class;
* @param obj The EntityType REST object to be converted
* @return The EntityType model object that is made from the REST object
*/
public EntityType toModel(EntityTypeRest obj) {
EntityType entityType = new EntityType();
entityType.setId(obj.getId());
entityType.setLabel(obj.getLabel());
return entityType;
} }
} }

View File

@@ -1,61 +0,0 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.converter;
import java.util.List;
import org.apache.log4j.Logger;
import org.dspace.app.rest.model.DSpaceObjectRest;
import org.dspace.content.DSpaceObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* This is the converter from/to an unknown DSpaceObject in the DSpace API data model and the
* REST data model
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class GenericDSpaceObjectConverter
extends DSpaceObjectConverter<org.dspace.content.DSpaceObject, org.dspace.app.rest.model.DSpaceObjectRest> {
@Autowired
private List<DSpaceObjectConverter> converters;
private static final Logger log = Logger.getLogger(GenericDSpaceObjectConverter.class);
/**
* Convert a DSpaceObject in its REST representation using a suitable converter
*/
@Override
public DSpaceObjectRest fromModel(org.dspace.content.DSpaceObject dspaceObject) {
for (DSpaceObjectConverter converter : converters) {
if (converter.supportsModel(dspaceObject)) {
return converter.fromModel(dspaceObject);
}
}
return null;
}
@Override
public org.dspace.content.DSpaceObject toModel(DSpaceObjectRest obj) {
return null;
}
@Override
protected DSpaceObjectRest newInstance() {
return null;
}
@Override
protected Class<DSpaceObject> getModelClass() {
return DSpaceObject.class;
}
}

View File

@@ -12,6 +12,7 @@ import java.util.List;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.eperson.Group; import org.dspace.eperson.Group;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -27,31 +28,25 @@ public class GroupConverter extends DSpaceObjectConverter<Group, org.dspace.app.
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(GroupConverter.class); private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(GroupConverter.class);
@Override @Override
public GroupRest fromModel(Group obj) { public GroupRest convert(Group obj, Projection projection) {
GroupRest epersongroup = super.fromModel(obj); GroupRest epersongroup = super.convert(obj, projection);
epersongroup.setPermanent(obj.isPermanent()); epersongroup.setPermanent(obj.isPermanent());
List<GroupRest> groups = new ArrayList<GroupRest>(); List<GroupRest> groups = new ArrayList<GroupRest>();
for (Group g : obj.getMemberGroups()) { for (Group g : obj.getMemberGroups()) {
groups.add(convert(g)); groups.add(convert(g, projection));
} }
epersongroup.setGroups(groups); epersongroup.setGroups(groups);
return epersongroup; return epersongroup;
} }
@Override
public Group toModel(GroupRest obj) {
// TODO Auto-generated method stub
return null;
}
@Override @Override
protected GroupRest newInstance() { protected GroupRest newInstance() {
return new GroupRest(); return new GroupRest();
} }
@Override @Override
protected Class<Group> getModelClass() { public Class<Group> getModelClass() {
return Group.class; return Group.class;
} }

View File

@@ -14,11 +14,11 @@ import org.dspace.app.rest.model.HarvestStatusEnum;
import org.dspace.app.rest.model.HarvestTypeEnum; import org.dspace.app.rest.model.HarvestTypeEnum;
import org.dspace.app.rest.model.HarvestedCollectionRest; import org.dspace.app.rest.model.HarvestedCollectionRest;
import org.dspace.app.rest.model.HarvesterMetadataRest; import org.dspace.app.rest.model.HarvesterMetadataRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.harvest.HarvestedCollection; import org.dspace.harvest.HarvestedCollection;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
/** /**
* This is the converter from/to the HarvestedCollection in the DSpace API data model and the REST data model * This is the converter from/to the HarvestedCollection in the DSpace API data model and the REST data model
@@ -29,18 +29,19 @@ import sun.reflect.generics.reflectiveObjects.NotImplementedException;
public class HarvestedCollectionConverter implements DSpaceConverter<HarvestedCollection, HarvestedCollectionRest> { public class HarvestedCollectionConverter implements DSpaceConverter<HarvestedCollection, HarvestedCollectionRest> {
@Autowired @Autowired
private CollectionConverter collectionConverter; private ConverterService converter;
@Override @Override
public HarvestedCollectionRest fromModel(HarvestedCollection obj) { public HarvestedCollectionRest convert(HarvestedCollection obj, Projection projection) {
HarvestedCollectionRest harvestedCollectionRest = new HarvestedCollectionRest(); HarvestedCollectionRest harvestedCollectionRest = new HarvestedCollectionRest();
harvestedCollectionRest.setProjection(projection);
if (obj != null) { if (obj != null) {
HarvestTypeEnum harvestTypeEnum = HarvestTypeEnum.fromInt(obj.getHarvestType()); HarvestTypeEnum harvestTypeEnum = HarvestTypeEnum.fromInt(obj.getHarvestType());
HarvestStatusEnum harvestStatusEnum = HarvestStatusEnum.fromInt(obj.getHarvestStatus()); HarvestStatusEnum harvestStatusEnum = HarvestStatusEnum.fromInt(obj.getHarvestStatus());
harvestedCollectionRest.setId(obj.getID()); harvestedCollectionRest.setId(obj.getID());
harvestedCollectionRest.setCollection(collectionConverter.fromModel(obj.getCollection())); harvestedCollectionRest.setCollection(converter.toRest(obj.getCollection(), projection));
harvestedCollectionRest.setHarvestType(harvestTypeEnum); harvestedCollectionRest.setHarvestType(harvestTypeEnum);
harvestedCollectionRest.setHarvestStatus(harvestStatusEnum); harvestedCollectionRest.setHarvestStatus(harvestStatusEnum);
harvestedCollectionRest.setMetadataConfigId(obj.getHarvestMetadataConfig()); harvestedCollectionRest.setMetadataConfigId(obj.getHarvestMetadataConfig());
@@ -59,24 +60,25 @@ public class HarvestedCollectionConverter implements DSpaceConverter<HarvestedCo
public HarvestedCollectionRest fromModel(HarvestedCollection obj, public HarvestedCollectionRest fromModel(HarvestedCollection obj,
Collection collection, Collection collection,
List<Map<String,String>> metadata_configs) { List<Map<String,String>> metadata_configs,
HarvestedCollectionRest harvestedCollectionRest = this.fromModel(obj); Projection projection) {
HarvestedCollectionRest harvestedCollectionRest = this.convert(obj, projection);
// Add collectionRest to the empty HarvestedCollectionRest so that we can use its uuid later in the linkFactory // Add collectionRest to the empty HarvestedCollectionRest so that we can use its uuid later in the linkFactory
if (obj == null) { if (obj == null) {
harvestedCollectionRest.setCollection(collectionConverter.fromModel(collection)); harvestedCollectionRest.setCollection(converter.toRest(collection, projection));
} }
HarvesterMetadataRest harvesterMetadataRest = new HarvesterMetadataRest(); HarvesterMetadataRest harvesterMetadataRest = new HarvesterMetadataRest();
harvesterMetadataRest.setProjection(projection);
harvesterMetadataRest.setConfigs(metadata_configs); harvesterMetadataRest.setConfigs(metadata_configs);
harvestedCollectionRest.setMetadataConfigs(harvesterMetadataRest); harvestedCollectionRest.setMetadataConfigs(harvesterMetadataRest);
return harvestedCollectionRest; return harvestedCollectionRest;
} }
@Override @Override
public HarvestedCollection toModel(HarvestedCollectionRest obj) { public Class<HarvestedCollection> getModelClass() {
throw new NotImplementedException(); return HarvestedCollection.class;
} }
} }

View File

@@ -26,6 +26,5 @@ public interface IndexableObjectConverter<M extends IndexableObject,
* the IndexableObject to check * the IndexableObject to check
* @return true if the actual converter implementation is able to manage the supplied IndexableObject * @return true if the actual converter implementation is able to manage the supplied IndexableObject
*/ */
public boolean supportsModel(IndexableObject idxo); boolean supportsModel(IndexableObject idxo);
}
}

View File

@@ -7,29 +7,19 @@
*/ */
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletRequest; import java.util.stream.Collectors;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.model.BitstreamRest; import org.dspace.app.rest.model.BundleRest;
import org.dspace.app.rest.model.ItemRest; import org.dspace.app.rest.model.ItemRest;
import org.dspace.app.rest.model.RelationshipRest; import org.dspace.app.rest.model.MetadataValueList;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataValue; import org.dspace.content.MetadataValue;
import org.dspace.content.Relationship;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.content.service.RelationshipService;
import org.dspace.core.Context;
import org.dspace.discovery.IndexableObject; import org.dspace.discovery.IndexableObject;
import org.dspace.services.RequestService;
import org.dspace.services.model.Request;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -41,100 +31,52 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
public class ItemConverter public class ItemConverter
extends DSpaceObjectConverter<org.dspace.content.Item, org.dspace.app.rest.model.ItemRest> extends DSpaceObjectConverter<Item, ItemRest>
implements IndexableObjectConverter<Item, ItemRest> { implements IndexableObjectConverter<Item, ItemRest> {
@Autowired(required = true)
private CollectionConverter collectionConverter;
@Autowired(required = true)
private BitstreamConverter bitstreamConverter;
@Autowired @Autowired
private RequestService requestService; private ConverterService converter;
@Autowired
private RelationshipService relationshipService;
@Autowired
private RelationshipConverter relationshipConverter;
@Autowired @Autowired
private ItemService itemService; private ItemService itemService;
@Autowired
private MetadataConverter metadataConverter;
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ItemConverter.class); private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ItemConverter.class);
@Override @Override
public ItemRest fromModel(org.dspace.content.Item obj) { public ItemRest convert(Item obj, Projection projection) {
ItemRest item = super.fromModel(obj); ItemRest item = super.convert(obj, projection);
item.setInArchive(obj.isArchived()); item.setInArchive(obj.isArchived());
item.setDiscoverable(obj.isDiscoverable()); item.setDiscoverable(obj.isDiscoverable());
item.setWithdrawn(obj.isWithdrawn()); item.setWithdrawn(obj.isWithdrawn());
item.setLastModified(obj.getLastModified()); item.setLastModified(obj.getLastModified());
try { Collection owningCollection = obj.getOwningCollection();
Collection c = obj.getOwningCollection(); if (owningCollection != null) {
if (c != null) { item.setOwningCollection(converter.toRest(owningCollection, projection));
item.setOwningCollection(collectionConverter.fromModel(c));
}
} catch (Exception e) {
log.error("Error setting owning collection for item" + item.getHandle(), e);
} }
try { Collection templateItemOf = obj.getTemplateItemOf();
Collection c = obj.getTemplateItemOf(); if (templateItemOf != null) {
if (c != null) { item.setTemplateItemOf(converter.toRest(templateItemOf, projection));
item.setTemplateItemOf(collectionConverter.fromModel(c));
}
} catch (Exception e) {
log.error("Error setting template item of for item " + item.getHandle(), e);
} }
List<BitstreamRest> bitstreams = new ArrayList<BitstreamRest>();
for (Bundle bun : obj.getBundles()) {
for (Bitstream bit : bun.getBitstreams()) {
BitstreamRest bitrest = bitstreamConverter.fromModel(bit);
bitstreams.add(bitrest);
}
}
item.setBitstreams(bitstreams);
List<Relationship> relationships = new LinkedList<>();
try {
Context context;
Request currentRequest = requestService.getCurrentRequest();
if (currentRequest != null) {
HttpServletRequest request = currentRequest.getHttpServletRequest();
context = ContextUtil.obtainContext(request);
} else {
context = new Context();
}
relationships = relationshipService.findByItem(context, obj);
} catch (SQLException e) {
log.error("Error retrieving relationships for item " + item.getHandle(), e);
}
List<RelationshipRest> relationshipRestList = new LinkedList<>();
for (Relationship relationship : relationships) {
RelationshipRest relationshipRest = relationshipConverter.fromModel(relationship);
relationshipRestList.add(relationshipRest);
}
item.setRelationships(relationshipRestList);
List<MetadataValue> fullList = new LinkedList<>(); item.setBundles(obj.getBundles()
fullList = itemService.getMetadata(obj, Item.ANY, Item.ANY, Item.ANY, Item.ANY, true); .stream()
.map(x -> (BundleRest) converter.toRest(x, projection))
item.setMetadata(metadataConverter.convert(fullList)); .collect(Collectors.toList()));
List<MetadataValue> fullList = itemService.getMetadata(obj, Item.ANY, Item.ANY, Item.ANY, Item.ANY, true);
MetadataValueList metadataValues = new MetadataValueList(fullList);
item.setMetadata(converter.toRest(metadataValues, projection));
return item; return item;
} }
@Override
public org.dspace.content.Item toModel(ItemRest obj) {
// TODO Auto-generated method stub
return null;
}
@Override @Override
protected ItemRest newInstance() { protected ItemRest newInstance() {
return new ItemRest(); return new ItemRest();
} }
@Override @Override
protected Class<Item> getModelClass() { public Class<Item> getModelClass() {
return Item.class; return Item.class;
} }

View File

@@ -17,7 +17,9 @@ import java.util.TreeSet;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.dspace.app.rest.model.MetadataRest; import org.dspace.app.rest.model.MetadataRest;
import org.dspace.app.rest.model.MetadataValueList;
import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.MetadataValueRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
@@ -26,39 +28,33 @@ import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.DSpaceObjectService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* Converter to translate between lists of domain {@link MetadataValue}s and {@link MetadataRest} representations. * Converter to translate between lists of domain {@link MetadataValue}s and {@link MetadataRest} representations.
*/ */
@Component @Component
public class MetadataConverter implements Converter<List<MetadataValue>, MetadataRest> { public class MetadataConverter implements DSpaceConverter<MetadataValueList, MetadataRest> {
@Autowired @Autowired
private ContentServiceFactory contentServiceFactory; private ContentServiceFactory contentServiceFactory;
@Autowired @Autowired
private MetadataValueConverter valueConverter; private ConverterService converter;
/**
* Gets a rest representation of the given list of domain metadata values.
*
* @param metadataValueList the domain values.
* @return the rest representation.
*/
@Override @Override
public MetadataRest convert(List<MetadataValue> metadataValueList) { public MetadataRest convert(MetadataValueList metadataValues,
Projection projection) {
// Convert each value to a DTO while retaining place order in a map of key -> SortedSet // Convert each value to a DTO while retaining place order in a map of key -> SortedSet
Map<String, SortedSet<MetadataValueRest>> mapOfSortedSets = new HashMap<>(); Map<String, SortedSet<MetadataValueRest>> mapOfSortedSets = new HashMap<>();
for (MetadataValue metadataValue : metadataValueList) { for (MetadataValue metadataValue : metadataValues) {
String key = metadataValue.getMetadataField().toString('.'); String key = metadataValue.getMetadataField().toString('.');
SortedSet<MetadataValueRest> set = mapOfSortedSets.get(key); SortedSet<MetadataValueRest> set = mapOfSortedSets.get(key);
if (set == null) { if (set == null) {
set = new TreeSet<>(Comparator.comparingInt(MetadataValueRest::getPlace)); set = new TreeSet<>(Comparator.comparingInt(MetadataValueRest::getPlace));
mapOfSortedSets.put(key, set); mapOfSortedSets.put(key, set);
} }
set.add(valueConverter.convert(metadataValue)); set.add(converter.toRest(metadataValue, projection));
} }
MetadataRest metadataRest = new MetadataRest(); MetadataRest metadataRest = new MetadataRest();
@@ -72,6 +68,11 @@ public class MetadataConverter implements Converter<List<MetadataValue>, Metadat
return metadataRest; return metadataRest;
} }
@Override
public Class<MetadataValueList> getModelClass() {
return MetadataValueList.class;
}
/** /**
* Sets a DSpace object's domain metadata values from a rest representation. * Sets a DSpace object's domain metadata values from a rest representation.
* *

View File

@@ -8,6 +8,8 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.MetadataFieldRest; import org.dspace.app.rest.model.MetadataFieldRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.MetadataField;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -18,24 +20,24 @@ import org.springframework.stereotype.Component;
* @author Andrea Bollini (andrea.bollini at 4science.it) * @author Andrea Bollini (andrea.bollini at 4science.it)
*/ */
@Component @Component
public class MetadataFieldConverter implements DSpaceConverter<org.dspace.content.MetadataField, MetadataFieldRest> { public class MetadataFieldConverter implements DSpaceConverter<MetadataField, MetadataFieldRest> {
@Autowired(required = true) @Autowired
private MetadataSchemaConverter metadataSchemaConverter; private ConverterService converter;
@Override @Override
public MetadataFieldRest fromModel(org.dspace.content.MetadataField obj) { public MetadataFieldRest convert(MetadataField obj, Projection projection) {
MetadataFieldRest field = new MetadataFieldRest(); MetadataFieldRest field = new MetadataFieldRest();
field.setProjection(projection);
field.setId(obj.getID()); field.setId(obj.getID());
field.setElement(obj.getElement()); field.setElement(obj.getElement());
field.setQualifier(obj.getQualifier()); field.setQualifier(obj.getQualifier());
field.setScopeNote(obj.getScopeNote()); field.setScopeNote(obj.getScopeNote());
field.setSchema(metadataSchemaConverter.convert(obj.getMetadataSchema())); field.setSchema(converter.toRest(obj.getMetadataSchema(), projection));
return field; return field;
} }
@Override @Override
public org.dspace.content.MetadataField toModel(MetadataFieldRest obj) { public Class<MetadataField> getModelClass() {
// TODO Auto-generated method stub return MetadataField.class;
return null;
} }
} }

View File

@@ -8,6 +8,8 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.MetadataSchemaRest; import org.dspace.app.rest.model.MetadataSchemaRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.MetadataSchema;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@@ -17,10 +19,11 @@ import org.springframework.stereotype.Component;
* @author Andrea Bollini (andrea.bollini at 4science.it) * @author Andrea Bollini (andrea.bollini at 4science.it)
*/ */
@Component @Component
public class MetadataSchemaConverter implements DSpaceConverter<org.dspace.content.MetadataSchema, MetadataSchemaRest> { public class MetadataSchemaConverter implements DSpaceConverter<MetadataSchema, MetadataSchemaRest> {
@Override @Override
public MetadataSchemaRest fromModel(org.dspace.content.MetadataSchema obj) { public MetadataSchemaRest convert(MetadataSchema obj, Projection projection) {
MetadataSchemaRest schema = new MetadataSchemaRest(); MetadataSchemaRest schema = new MetadataSchemaRest();
schema.setProjection(projection);
schema.setId(obj.getID()); schema.setId(obj.getID());
schema.setNamespace(obj.getNamespace()); schema.setNamespace(obj.getNamespace());
schema.setPrefix(obj.getName()); schema.setPrefix(obj.getName());
@@ -28,8 +31,7 @@ public class MetadataSchemaConverter implements DSpaceConverter<org.dspace.conte
} }
@Override @Override
public org.dspace.content.MetadataSchema toModel(MetadataSchemaRest obj) { public Class<MetadataSchema> getModelClass() {
// TODO Auto-generated method stub return MetadataSchema.class;
return null;
} }
} }

View File

@@ -8,24 +8,18 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.MetadataValueRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.MetadataValue; import org.dspace.content.MetadataValue;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* Converter to translate between domain {@link MetadataValue}s and {@link MetadataValueRest} representations. * Converter to translate between domain {@link MetadataValue}s and {@link MetadataValueRest} representations.
*/ */
@Component @Component
public class MetadataValueConverter implements Converter<MetadataValue, MetadataValueRest> { public class MetadataValueConverter implements DSpaceConverter<MetadataValue, MetadataValueRest> {
/**
* Gets a rest representation of the given domain metadata value.
*
* @param metadataValue the domain value.
* @return the rest representation.
*/
@Override @Override
public MetadataValueRest convert(MetadataValue metadataValue) { public MetadataValueRest convert(MetadataValue metadataValue, Projection projection) {
MetadataValueRest metadataValueRest = new MetadataValueRest(); MetadataValueRest metadataValueRest = new MetadataValueRest();
metadataValueRest.setValue(metadataValue.getValue()); metadataValueRest.setValue(metadataValue.getValue());
metadataValueRest.setLanguage(metadataValue.getLanguage()); metadataValueRest.setLanguage(metadataValue.getLanguage());
@@ -34,4 +28,9 @@ public class MetadataValueConverter implements Converter<MetadataValue, Metadata
metadataValueRest.setPlace(metadataValue.getPlace()); metadataValueRest.setPlace(metadataValue.getPlace());
return metadataValueRest; return metadataValueRest;
} }
@Override
public Class<MetadataValue> getModelClass() {
return MetadataValue.class;
}
} }

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.PoolTaskRest; import org.dspace.app.rest.model.PoolTaskRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.discovery.IndexableObject; import org.dspace.discovery.IndexableObject;
import org.dspace.xmlworkflow.storedcomponents.PoolTask; import org.dspace.xmlworkflow.storedcomponents.PoolTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
@@ -25,26 +26,21 @@ public class PoolTaskConverter
implements IndexableObjectConverter<PoolTask, org.dspace.app.rest.model.PoolTaskRest> { implements IndexableObjectConverter<PoolTask, org.dspace.app.rest.model.PoolTaskRest> {
@Autowired @Autowired
private WorkflowItemConverter workflowItemConverter; private ConverterService converter;
@Autowired
private EPersonConverter epersonConverter;
@Autowired
private GroupConverter groupConverter;
@Override @Override
public PoolTaskRest fromModel(PoolTask obj) { public PoolTaskRest convert(PoolTask obj, Projection projection) {
PoolTaskRest taskRest = new PoolTaskRest(); PoolTaskRest taskRest = new PoolTaskRest();
taskRest.setProjection(projection);
XmlWorkflowItem witem = obj.getWorkflowItem(); XmlWorkflowItem witem = obj.getWorkflowItem();
taskRest.setId(obj.getID()); taskRest.setId(obj.getID());
taskRest.setWorkflowitem(workflowItemConverter.convert(witem)); taskRest.setWorkflowitem(converter.toRest(witem, projection));
if (obj.getEperson() != null) { if (obj.getEperson() != null) {
taskRest.setEperson(epersonConverter.convert(obj.getEperson())); taskRest.setEperson(converter.toRest(obj.getEperson(), projection));
} }
if (obj.getGroup() != null) { if (obj.getGroup() != null) {
taskRest.setGroup(groupConverter.convert(obj.getGroup())); taskRest.setGroup(converter.toRest(obj.getGroup(), projection));
} }
taskRest.setAction(obj.getActionID()); taskRest.setAction(obj.getActionID());
taskRest.setStep(obj.getStepID()); taskRest.setStep(obj.getStepID());
@@ -52,8 +48,8 @@ public class PoolTaskConverter
} }
@Override @Override
public PoolTask toModel(PoolTaskRest obj) { public Class<PoolTask> getModelClass() {
return null; return PoolTask.class;
} }
@Override @Override
@@ -61,4 +57,4 @@ public class PoolTaskConverter
return object instanceof PoolTask; return object instanceof PoolTask;
} }
} }

View File

@@ -0,0 +1,52 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.converter;
import java.util.stream.Collectors;
import org.dspace.app.rest.model.ParameterValueRest;
import org.dspace.app.rest.model.ProcessRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.scripts.Process;
import org.dspace.scripts.service.ProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* This converter will convert an object of {@Link Process} to an object of {@link ProcessRest}
*/
@Component
public class ProcessConverter implements DSpaceConverter<Process, ProcessRest> {
@Autowired
private ConverterService converter;
@Autowired
private ProcessService processService;
@Override
public ProcessRest convert(Process process, Projection projection) {
ProcessRest processRest = new ProcessRest();
processRest.setProjection(projection);
processRest.setId(process.getID());
processRest.setScriptName(process.getName());
processRest.setProcessId(process.getID());
processRest.setUserId(process.getEPerson().getID());
processRest.setProcessStatus(process.getProcessStatus());
processRest.setStartTime(process.getStartTime());
processRest.setEndTime(process.getFinishedTime());
processRest.setParameterRestList(processService.getParameters(process).stream()
.map(x -> (ParameterValueRest) converter.toRest(x, projection)).collect(Collectors.toList()));
return processRest;
}
@Override
public Class<Process> getModelClass() {
return Process.class;
}
}

View File

@@ -8,10 +8,10 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.RelationshipRest; import org.dspace.app.rest.model.RelationshipRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Relationship; import org.dspace.content.Relationship;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
/** /**
* This converter is responsible for transforming the model representation of an Relationship to the REST * This converter is responsible for transforming the model representation of an Relationship to the REST
@@ -21,20 +21,15 @@ import sun.reflect.generics.reflectiveObjects.NotImplementedException;
public class RelationshipConverter implements DSpaceConverter<Relationship, RelationshipRest> { public class RelationshipConverter implements DSpaceConverter<Relationship, RelationshipRest> {
@Autowired @Autowired
private RelationshipTypeConverter relationshipTypeConverter; private ConverterService converter;
@Override
/** public RelationshipRest convert(Relationship obj, Projection projection) {
* This method converts the Relationship model object that is passed along in the params to the
* REST representation of this object
* @param obj The Relationship model object to be converted
* @return The Relationship REST object that is made from the model object
*/
public RelationshipRest fromModel(Relationship obj) {
RelationshipRest relationshipRest = new RelationshipRest(); RelationshipRest relationshipRest = new RelationshipRest();
relationshipRest.setProjection(projection);
relationshipRest.setId(obj.getID()); relationshipRest.setId(obj.getID());
relationshipRest.setLeftId(obj.getLeftItem().getID()); relationshipRest.setLeftId(obj.getLeftItem().getID());
relationshipRest.setRelationshipType(relationshipTypeConverter.fromModel(obj.getRelationshipType())); relationshipRest.setRelationshipType(converter.toRest(obj.getRelationshipType(), projection));
relationshipRest.setRightId(obj.getRightItem().getID()); relationshipRest.setRightId(obj.getRightItem().getID());
relationshipRest.setLeftPlace(obj.getLeftPlace()); relationshipRest.setLeftPlace(obj.getLeftPlace());
relationshipRest.setRightPlace(obj.getRightPlace()); relationshipRest.setRightPlace(obj.getRightPlace());
@@ -43,13 +38,8 @@ public class RelationshipConverter implements DSpaceConverter<Relationship, Rela
return relationshipRest; return relationshipRest;
} }
/** @Override
* This method converts the Relationship REST object that is passed along in the params to the model public Class<Relationship> getModelClass() {
* representation of this object return Relationship.class;
* @param obj The Relationship REST object to be converted
* @return The Relationship model object that is made from the REST object
*/
public Relationship toModel(RelationshipRest obj) {
throw new NotImplementedException();
} }
} }

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.RelationshipTypeRest; import org.dspace.app.rest.model.RelationshipTypeRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.RelationshipType; import org.dspace.content.RelationshipType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -20,16 +21,12 @@ import org.springframework.stereotype.Component;
public class RelationshipTypeConverter implements DSpaceConverter<RelationshipType, RelationshipTypeRest> { public class RelationshipTypeConverter implements DSpaceConverter<RelationshipType, RelationshipTypeRest> {
@Autowired @Autowired
private EntityTypeConverter entityTypeConverter; private ConverterService converter;
/** @Override
* This method converts the RelationshipType model object that is passed along in the params to the public RelationshipTypeRest convert(RelationshipType obj, Projection projection) {
* REST representation of this object
* @param obj The RelationshipType model object to be converted
* @return The RelationshipType REST object that is made from the model object
*/
public RelationshipTypeRest fromModel(RelationshipType obj) {
RelationshipTypeRest relationshipTypeRest = new RelationshipTypeRest(); RelationshipTypeRest relationshipTypeRest = new RelationshipTypeRest();
relationshipTypeRest.setProjection(projection);
relationshipTypeRest.setId(obj.getID()); relationshipTypeRest.setId(obj.getID());
relationshipTypeRest.setLeftwardType(obj.getLeftwardType()); relationshipTypeRest.setLeftwardType(obj.getLeftwardType());
@@ -38,20 +35,14 @@ public class RelationshipTypeConverter implements DSpaceConverter<RelationshipTy
relationshipTypeRest.setLeftMaxCardinality(obj.getLeftMaxCardinality()); relationshipTypeRest.setLeftMaxCardinality(obj.getLeftMaxCardinality());
relationshipTypeRest.setRightMinCardinality(obj.getRightMinCardinality()); relationshipTypeRest.setRightMinCardinality(obj.getRightMinCardinality());
relationshipTypeRest.setRightMaxCardinality(obj.getRightMaxCardinality()); relationshipTypeRest.setRightMaxCardinality(obj.getRightMaxCardinality());
relationshipTypeRest.setLeftType(entityTypeConverter.fromModel(obj.getLeftType())); relationshipTypeRest.setLeftType(converter.toRest(obj.getLeftType(), projection));
relationshipTypeRest.setRightType(entityTypeConverter.fromModel(obj.getRightType())); relationshipTypeRest.setRightType(converter.toRest(obj.getRightType(), projection));
return relationshipTypeRest; return relationshipTypeRest;
} }
/** @Override
* This method converts the RelationshipType REST object that is passed along in the params to the model public Class<RelationshipType> getModelClass() {
* representation of this object return RelationshipType.class;
* @param obj The RelationshipType REST object to be converted
* @return The RelationshipType model object that is made from the REST object
*/
public RelationshipType toModel(RelationshipTypeRest obj) {
return null;
} }
} }

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.ResourcePolicyRest; import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.authorize.service.ResourcePolicyService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -26,9 +27,10 @@ public class ResourcePolicyConverter implements DSpaceConverter<ResourcePolicy,
ResourcePolicyService resourcePolicyService; ResourcePolicyService resourcePolicyService;
@Override @Override
public ResourcePolicyRest fromModel(ResourcePolicy obj) { public ResourcePolicyRest convert(ResourcePolicy obj, Projection projection) {
ResourcePolicyRest model = new ResourcePolicyRest(); ResourcePolicyRest model = new ResourcePolicyRest();
model.setProjection(projection);
model.setId(obj.getID()); model.setId(obj.getID());
@@ -52,9 +54,8 @@ public class ResourcePolicyConverter implements DSpaceConverter<ResourcePolicy,
} }
@Override @Override
public ResourcePolicy toModel(ResourcePolicyRest obj) { public Class<ResourcePolicy> getModelClass() {
// TODO Auto-generated method stub return ResourcePolicy.class;
return null;
} }
} }

View File

@@ -0,0 +1,53 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.converter;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.cli.Option;
import org.apache.commons.collections4.CollectionUtils;
import org.dspace.app.rest.model.ParameterRest;
import org.dspace.app.rest.model.ScriptRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.scripts.DSpaceRunnable;
import org.springframework.stereotype.Component;
/**
* This converter will convert an object of {@Link DSpaceRunnable} to an object
* of {@link ScriptRest}
*/
@Component
public class ScriptConverter implements DSpaceConverter<DSpaceRunnable, ScriptRest> {
@Override
public ScriptRest convert(DSpaceRunnable script, Projection projection) {
ScriptRest scriptRest = new ScriptRest();
scriptRest.setProjection(projection);
scriptRest.setDescription(script.getDescription());
scriptRest.setId(script.getName());
scriptRest.setName(script.getName());
List<ParameterRest> parameterRestList = new LinkedList<>();
for (Option option : CollectionUtils.emptyIfNull(script.getOptions().getOptions())) {
ParameterRest parameterRest = new ParameterRest();
parameterRest.setDescription(option.getDescription());
parameterRest.setName((option.getOpt() != null ? "-" + option.getOpt() : "--" + option.getLongOpt()));
parameterRest.setType(((Class) option.getType()).getSimpleName());
parameterRestList.add(parameterRest);
}
scriptRest.setParameterRestList(parameterRestList);
return scriptRest;
}
@Override
public Class<DSpaceRunnable> getModelClass() {
return DSpaceRunnable.class;
}
}

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.converter; package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.SiteRest; import org.dspace.app.rest.model.SiteRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Site; import org.dspace.content.Site;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -18,16 +19,11 @@ import org.springframework.stereotype.Component;
* @author Andrea Bollini (andrea.bollini at 4science.it) * @author Andrea Bollini (andrea.bollini at 4science.it)
*/ */
@Component @Component
public class SiteConverter public class SiteConverter extends DSpaceObjectConverter<Site, SiteRest> {
extends DSpaceObjectConverter<org.dspace.content.Site, org.dspace.app.rest.model.SiteRest> {
@Override
public org.dspace.content.Site toModel(org.dspace.app.rest.model.SiteRest obj) {
return (org.dspace.content.Site) super.toModel(obj);
}
@Override @Override
public SiteRest fromModel(org.dspace.content.Site obj) { public SiteRest convert(Site obj, Projection projection) {
return (SiteRest) super.fromModel(obj); return super.convert(obj, projection);
} }
@Override @Override
@@ -36,7 +32,7 @@ public class SiteConverter
} }
@Override @Override
protected Class<Site> getModelClass() { public Class<Site> getModelClass() {
return Site.class; return Site.class;
} }
} }

View File

@@ -13,11 +13,11 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.model.CollectionRest; import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.SubmissionDefinitionRest; import org.dspace.app.rest.model.SubmissionDefinitionRest;
import org.dspace.app.rest.model.SubmissionSectionRest; import org.dspace.app.rest.model.SubmissionSectionRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.util.SubmissionConfig; import org.dspace.app.util.SubmissionConfig;
import org.dspace.app.util.SubmissionConfigReaderException; import org.dspace.app.util.SubmissionConfigReaderException;
@@ -47,17 +47,18 @@ public class SubmissionDefinitionConverter implements DSpaceConverter<Submission
private RequestService requestService; private RequestService requestService;
@Autowired @Autowired
private CollectionConverter collectionConverter; private ConverterService converter;
@Override @Override
public SubmissionDefinitionRest fromModel(SubmissionConfig obj) { public SubmissionDefinitionRest convert(SubmissionConfig obj, Projection projection) {
SubmissionDefinitionRest sd = new SubmissionDefinitionRest(); SubmissionDefinitionRest sd = new SubmissionDefinitionRest();
sd.setProjection(projection);
sd.setName(obj.getSubmissionName()); sd.setName(obj.getSubmissionName());
sd.setDefaultConf(obj.isDefaultConf()); sd.setDefaultConf(obj.isDefaultConf());
List<SubmissionSectionRest> panels = new LinkedList<SubmissionSectionRest>(); List<SubmissionSectionRest> panels = new LinkedList<SubmissionSectionRest>();
for (int idx = 0; idx < obj.getNumberOfSteps(); idx++) { for (int idx = 0; idx < obj.getNumberOfSteps(); idx++) {
SubmissionStepConfig step = obj.getStep(idx); SubmissionStepConfig step = obj.getStep(idx);
SubmissionSectionRest sp = panelConverter.convert(step); SubmissionSectionRest sp = converter.toRest(step, projection);
panels.add(sp); panels.add(sp);
} }
@@ -68,8 +69,9 @@ public class SubmissionDefinitionConverter implements DSpaceConverter<Submission
List<Collection> collections = panelConverter.getSubmissionConfigReader() List<Collection> collections = panelConverter.getSubmissionConfigReader()
.getCollectionsBySubmissionConfig(context, .getCollectionsBySubmissionConfig(context,
obj.getSubmissionName()); obj.getSubmissionName());
List<CollectionRest> collectionsRest = collections.stream().map( DSpaceConverter<Collection, CollectionRest> cc = converter.getConverter(Collection.class);
(collection) -> collectionConverter.convert(collection)).collect(Collectors.toList()); List<CollectionRest> collectionsRest = collections.stream().map((collection) ->
cc.convert(collection, projection)).collect(Collectors.toList());
sd.setCollections(collectionsRest); sd.setCollections(collectionsRest);
} catch (SQLException | IllegalStateException | SubmissionConfigReaderException e) { } catch (SQLException | IllegalStateException | SubmissionConfigReaderException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
@@ -79,7 +81,7 @@ public class SubmissionDefinitionConverter implements DSpaceConverter<Submission
} }
@Override @Override
public SubmissionConfig toModel(SubmissionDefinitionRest obj) { public Class<SubmissionConfig> getModelClass() {
throw new NotImplementedException("Method not implemented"); return SubmissionConfig.class;
} }
} }

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