mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-12 20:43:18 +00:00
Merge branch 'master' of https://github.com/DSpace/DSpace into CST-3091
This commit is contained in:
9
.lgtm.yml
Normal file
9
.lgtm.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# LGTM Settings (https://lgtm.com/)
|
||||||
|
# For reference, see https://lgtm.com/help/lgtm/lgtm.yml-configuration-file
|
||||||
|
# or template at https://lgtm.com/static/downloads/lgtm.template.yml
|
||||||
|
|
||||||
|
extraction:
|
||||||
|
java:
|
||||||
|
index:
|
||||||
|
# Specify the Java version required to build the project
|
||||||
|
java_version: 11
|
@@ -8,14 +8,10 @@
|
|||||||
package org.dspace.app.bulkedit;
|
package org.dspace.app.bulkedit;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.InputStream;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -27,6 +23,7 @@ import java.util.UUID;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.authority.AuthorityValue;
|
import org.dspace.authority.AuthorityValue;
|
||||||
import org.dspace.authority.factory.AuthorityServiceFactory;
|
import org.dspace.authority.factory.AuthorityServiceFactory;
|
||||||
@@ -141,18 +138,18 @@ public class DSpaceCSV implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* Create a new instance, reading the lines in from file
|
* Create a new instance, reading the lines in from file
|
||||||
*
|
*
|
||||||
* @param f The file to read from
|
* @param inputStream the inputstream to read from
|
||||||
* @param c The DSpace Context
|
* @param c The DSpace Context
|
||||||
* @throws Exception thrown if there is an error reading or processing the file
|
* @throws Exception thrown if there is an error reading or processing the file
|
||||||
*/
|
*/
|
||||||
public DSpaceCSV(File f, Context c) throws Exception {
|
public DSpaceCSV(InputStream inputStream, Context c) throws Exception {
|
||||||
// Initialise the class
|
// Initialise the class
|
||||||
init();
|
init();
|
||||||
|
|
||||||
// Open the CSV file
|
// Open the CSV file
|
||||||
BufferedReader input = null;
|
BufferedReader input = null;
|
||||||
try {
|
try {
|
||||||
input = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
|
input = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||||
|
|
||||||
// Read the heading line
|
// Read the heading line
|
||||||
String head = input.readLine();
|
String head = input.readLine();
|
||||||
@@ -623,21 +620,15 @@ public class DSpaceCSV implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the CSV file to the given filename
|
* Creates and returns an InputStream from the CSV Lines in this DSpaceCSV
|
||||||
*
|
* @return The InputStream created from the CSVLines in this DSpaceCSV
|
||||||
* @param filename The filename to save the CSV file to
|
|
||||||
* @throws IOException Thrown if an error occurs when writing the file
|
|
||||||
*/
|
*/
|
||||||
public final void save(String filename) throws IOException {
|
public InputStream getInputStream() {
|
||||||
// Save the file
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
BufferedWriter out = new BufferedWriter(
|
|
||||||
new OutputStreamWriter(
|
|
||||||
new FileOutputStream(filename), "UTF-8"));
|
|
||||||
for (String csvLine : getCSVLinesAsStringArray()) {
|
for (String csvLine : getCSVLinesAsStringArray()) {
|
||||||
out.write(csvLine + "\n");
|
stringBuilder.append(csvLine + "\n");
|
||||||
}
|
}
|
||||||
out.flush();
|
return IOUtils.toInputStream(stringBuilder.toString(), StandardCharsets.UTF_8);
|
||||||
out.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -8,271 +8,84 @@
|
|||||||
package org.dspace.app.bulkedit;
|
package org.dspace.app.bulkedit;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.common.collect.Iterators;
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
|
||||||
import org.apache.commons.cli.HelpFormatter;
|
|
||||||
import org.apache.commons.cli.Options;
|
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.cli.PosixParser;
|
import org.dspace.content.service.MetadataDSpaceCsvExportService;
|
||||||
import org.dspace.content.Collection;
|
|
||||||
import org.dspace.content.Community;
|
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.content.Item;
|
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
|
||||||
import org.dspace.content.service.ItemService;
|
|
||||||
import org.dspace.core.Constants;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.handle.factory.HandleServiceFactory;
|
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||||
|
import org.dspace.eperson.service.EPersonService;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata exporter to allow the batch export of metadata into a file
|
* Metadata exporter to allow the batch export of metadata into a file
|
||||||
*
|
*
|
||||||
* @author Stuart Lewis
|
* @author Stuart Lewis
|
||||||
*/
|
*/
|
||||||
public class MetadataExport {
|
public class MetadataExport extends DSpaceRunnable<MetadataExportScriptConfiguration> {
|
||||||
/**
|
|
||||||
* The items to export
|
|
||||||
*/
|
|
||||||
protected Iterator<Item> toExport;
|
|
||||||
|
|
||||||
protected ItemService itemService;
|
private boolean help = false;
|
||||||
|
private String filename = null;
|
||||||
|
private String handle = null;
|
||||||
|
private boolean exportAllMetadata = false;
|
||||||
|
private boolean exportAllItems = false;
|
||||||
|
|
||||||
protected Context context;
|
private static final String EXPORT_CSV = "exportCSV";
|
||||||
|
|
||||||
/**
|
private MetadataDSpaceCsvExportService metadataDSpaceCsvExportService = new DSpace().getServiceManager()
|
||||||
* Whether to export all metadata, or just normally edited metadata
|
.getServicesByType(MetadataDSpaceCsvExportService.class).get(0);
|
||||||
*/
|
|
||||||
protected boolean exportAll;
|
|
||||||
|
|
||||||
protected MetadataExport() {
|
private EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||||
itemService = ContentServiceFactory.getInstance().getItemService();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Set up a new metadata export
|
public void internalRun() throws Exception {
|
||||||
*
|
|
||||||
* @param c The Context
|
|
||||||
* @param toExport The ItemIterator of items to export
|
|
||||||
* @param exportAll whether to export all metadata or not (include handle, provenance etc)
|
|
||||||
*/
|
|
||||||
public MetadataExport(Context c, Iterator<Item> toExport, boolean exportAll) {
|
|
||||||
itemService = ContentServiceFactory.getInstance().getItemService();
|
|
||||||
|
|
||||||
// Store the export settings
|
|
||||||
this.toExport = toExport;
|
|
||||||
this.exportAll = exportAll;
|
|
||||||
this.context = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to export a community (and sub-communities and collections)
|
|
||||||
*
|
|
||||||
* @param c The Context
|
|
||||||
* @param toExport The Community to export
|
|
||||||
* @param exportAll whether to export all metadata or not (include handle, provenance etc)
|
|
||||||
*/
|
|
||||||
public MetadataExport(Context c, Community toExport, boolean exportAll) {
|
|
||||||
itemService = ContentServiceFactory.getInstance().getItemService();
|
|
||||||
|
|
||||||
|
if (help) {
|
||||||
|
handler.logInfo("\nfull export: metadata-export -f filename");
|
||||||
|
handler.logInfo("partial export: metadata-export -i handle -f filename");
|
||||||
|
printHelp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Context context = new Context();
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
try {
|
try {
|
||||||
// Try to export the community
|
context.setCurrentUser(ePersonService.find(context, this.getEpersonIdentifier()));
|
||||||
this.toExport = buildFromCommunity(c, toExport, 0);
|
} catch (SQLException e) {
|
||||||
this.exportAll = exportAll;
|
handler.handleException(e);
|
||||||
this.context = c;
|
|
||||||
} catch (SQLException sqle) {
|
|
||||||
// Something went wrong...
|
|
||||||
System.err.println("Error running exporter:");
|
|
||||||
sqle.printStackTrace(System.err);
|
|
||||||
System.exit(1);
|
|
||||||
}
|
}
|
||||||
|
DSpaceCSV dSpaceCSV = metadataDSpaceCsvExportService
|
||||||
|
.handleExport(context, exportAllItems, exportAllMetadata, handle,
|
||||||
|
handler);
|
||||||
|
handler.writeFilestream(context, filename, dSpaceCSV.getInputStream(), EXPORT_CSV);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
context.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Build an array list of item ids that are in a community (include sub-communities and collections)
|
public MetadataExportScriptConfiguration getScriptConfiguration() {
|
||||||
*
|
return new DSpace().getServiceManager().getServiceByName("metadata-export",
|
||||||
* @param context DSpace context
|
MetadataExportScriptConfiguration.class);
|
||||||
* @param community The community to build from
|
|
||||||
* @param indent How many spaces to use when writing out the names of items added
|
|
||||||
* @return The list of item ids
|
|
||||||
* @throws SQLException if database error
|
|
||||||
*/
|
|
||||||
protected Iterator<Item> buildFromCommunity(Context context, Community community, int indent)
|
|
||||||
throws SQLException {
|
|
||||||
// Add all the collections
|
|
||||||
List<Collection> collections = community.getCollections();
|
|
||||||
Iterator<Item> result = null;
|
|
||||||
for (Collection collection : collections) {
|
|
||||||
for (int i = 0; i < indent; i++) {
|
|
||||||
System.out.print(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<Item> items = itemService.findByCollection(context, collection);
|
|
||||||
result = addItemsToResult(result, items);
|
|
||||||
|
|
||||||
}
|
|
||||||
// Add all the sub-communities
|
|
||||||
List<Community> communities = community.getSubcommunities();
|
|
||||||
for (Community subCommunity : communities) {
|
|
||||||
for (int i = 0; i < indent; i++) {
|
|
||||||
System.out.print(" ");
|
|
||||||
}
|
|
||||||
Iterator<Item> items = buildFromCommunity(context, subCommunity, indent + 1);
|
|
||||||
result = addItemsToResult(result, items);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Iterator<Item> addItemsToResult(Iterator<Item> result, Iterator<Item> items) {
|
@Override
|
||||||
if (result == null) {
|
public void setup() throws ParseException {
|
||||||
result = items;
|
|
||||||
} else {
|
|
||||||
result = Iterators.concat(result, items);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
if (commandLine.hasOption('h')) {
|
||||||
}
|
help = true;
|
||||||
|
return;
|
||||||
/**
|
|
||||||
* Run the export
|
|
||||||
*
|
|
||||||
* @return the exported CSV lines
|
|
||||||
*/
|
|
||||||
public DSpaceCSV export() {
|
|
||||||
try {
|
|
||||||
Context.Mode originalMode = context.getCurrentMode();
|
|
||||||
context.setMode(Context.Mode.READ_ONLY);
|
|
||||||
|
|
||||||
// Process each item
|
|
||||||
DSpaceCSV csv = new DSpaceCSV(exportAll);
|
|
||||||
while (toExport.hasNext()) {
|
|
||||||
Item item = toExport.next();
|
|
||||||
csv.addItem(item);
|
|
||||||
context.uncacheEntity(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.setMode(originalMode);
|
|
||||||
// Return the results
|
|
||||||
return csv;
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Something went wrong...
|
|
||||||
System.err.println("Error exporting to CSV:");
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print the help message
|
|
||||||
*
|
|
||||||
* @param options The command line options the user gave
|
|
||||||
* @param exitCode the system exit code to use
|
|
||||||
*/
|
|
||||||
private static void printHelp(Options options, int exitCode) {
|
|
||||||
// print the help message
|
|
||||||
HelpFormatter myhelp = new HelpFormatter();
|
|
||||||
myhelp.printHelp("MetadataExport\n", options);
|
|
||||||
System.out.println("\nfull export: metadataexport -f filename");
|
|
||||||
System.out.println("partial export: metadataexport -i handle -f filename");
|
|
||||||
System.exit(exitCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* main method to run the metadata exporter
|
|
||||||
*
|
|
||||||
* @param argv the command line arguments given
|
|
||||||
* @throws Exception if error occurs
|
|
||||||
*/
|
|
||||||
public static void main(String[] argv) throws Exception {
|
|
||||||
// Create an options object and populate it
|
|
||||||
CommandLineParser parser = new PosixParser();
|
|
||||||
|
|
||||||
Options options = new Options();
|
|
||||||
|
|
||||||
options.addOption("i", "id", true, "ID or handle of thing to export (item, collection, or community)");
|
|
||||||
options.addOption("f", "file", true, "destination where you want file written");
|
|
||||||
options.addOption("a", "all", false,
|
|
||||||
"include all metadata fields that are not normally changed (e.g. provenance)");
|
|
||||||
options.addOption("h", "help", false, "help");
|
|
||||||
|
|
||||||
CommandLine line = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
line = parser.parse(options, argv);
|
|
||||||
} catch (ParseException pe) {
|
|
||||||
System.err.println("Error with commands.");
|
|
||||||
printHelp(options, 1);
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.hasOption('h')) {
|
|
||||||
printHelp(options, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check a filename is given
|
// Check a filename is given
|
||||||
if (!line.hasOption('f')) {
|
if (!commandLine.hasOption('f')) {
|
||||||
System.err.println("Required parameter -f missing!");
|
throw new ParseException("Required parameter -f missing!");
|
||||||
printHelp(options, 1);
|
|
||||||
}
|
}
|
||||||
String filename = line.getOptionValue('f');
|
filename = commandLine.getOptionValue('f');
|
||||||
|
|
||||||
// Create a context
|
exportAllMetadata = commandLine.hasOption('a');
|
||||||
Context c = new Context(Context.Mode.READ_ONLY);
|
|
||||||
c.turnOffAuthorisationSystem();
|
|
||||||
|
|
||||||
// The things we'll export
|
if (!commandLine.hasOption('i')) {
|
||||||
Iterator<Item> toExport = null;
|
exportAllItems = true;
|
||||||
MetadataExport exporter = null;
|
|
||||||
|
|
||||||
// Export everything?
|
|
||||||
boolean exportAll = line.hasOption('a');
|
|
||||||
|
|
||||||
ContentServiceFactory contentServiceFactory = ContentServiceFactory.getInstance();
|
|
||||||
// Check we have an item OK
|
|
||||||
ItemService itemService = contentServiceFactory.getItemService();
|
|
||||||
if (!line.hasOption('i')) {
|
|
||||||
System.out.println("Exporting whole repository WARNING: May take some time!");
|
|
||||||
exporter = new MetadataExport(c, itemService.findAll(c), exportAll);
|
|
||||||
} else {
|
|
||||||
String handle = line.getOptionValue('i');
|
|
||||||
DSpaceObject dso = HandleServiceFactory.getInstance().getHandleService().resolveToObject(c, handle);
|
|
||||||
if (dso == null) {
|
|
||||||
System.err.println("Item '" + handle + "' does not resolve to an item in your repository!");
|
|
||||||
printHelp(options, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dso.getType() == Constants.ITEM) {
|
|
||||||
System.out.println("Exporting item '" + dso.getName() + "' (" + handle + ")");
|
|
||||||
List<Item> item = new ArrayList<>();
|
|
||||||
item.add((Item) dso);
|
|
||||||
exporter = new MetadataExport(c, item.iterator(), exportAll);
|
|
||||||
} else if (dso.getType() == Constants.COLLECTION) {
|
|
||||||
System.out.println("Exporting collection '" + dso.getName() + "' (" + handle + ")");
|
|
||||||
Collection collection = (Collection) dso;
|
|
||||||
toExport = itemService.findByCollection(c, collection);
|
|
||||||
exporter = new MetadataExport(c, toExport, exportAll);
|
|
||||||
} else if (dso.getType() == Constants.COMMUNITY) {
|
|
||||||
System.out.println("Exporting community '" + dso.getName() + "' (" + handle + ")");
|
|
||||||
exporter = new MetadataExport(c, (Community) dso, exportAll);
|
|
||||||
} else {
|
|
||||||
System.err.println("Error identifying '" + handle + "'");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
handle = commandLine.getOptionValue('i');
|
||||||
// Perform the export
|
|
||||||
DSpaceCSV csv = exporter.export();
|
|
||||||
|
|
||||||
// Save the files to the file
|
|
||||||
csv.save(filename);
|
|
||||||
|
|
||||||
// Finish off and tidy up
|
|
||||||
c.restoreAuthSystemState();
|
|
||||||
c.complete();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkedit;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ScriptConfiguration} for the {@link MetadataExport} script
|
||||||
|
*/
|
||||||
|
public class MetadataExportScriptConfiguration<T extends MetadataExport> extends ScriptConfiguration<T> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
private Class<T> dspaceRunnableClass;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getDspaceRunnableClass() {
|
||||||
|
return dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the dspaceRunnableClass
|
||||||
|
* @param dspaceRunnableClass The dspaceRunnableClass to be set on this MetadataExportScriptConfiguration
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
|
||||||
|
this.dspaceRunnableClass = dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowedToExecute(Context context) {
|
||||||
|
try {
|
||||||
|
return authorizeService.isAdmin(context);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("SQLException occurred when checking if the current user is an admin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Options getOptions() {
|
||||||
|
if (options == null) {
|
||||||
|
Options options = new Options();
|
||||||
|
|
||||||
|
options.addOption("i", "id", true, "ID or handle of thing to export (item, collection, or community)");
|
||||||
|
options.getOption("i").setType(String.class);
|
||||||
|
options.addOption("f", "file", true, "destination where you want file written");
|
||||||
|
options.getOption("f").setType(OutputStream.class);
|
||||||
|
options.getOption("f").setRequired(true);
|
||||||
|
options.addOption("a", "all", false,
|
||||||
|
"include all metadata fields that are not normally changed (e.g. provenance)");
|
||||||
|
options.getOption("a").setType(boolean.class);
|
||||||
|
options.addOption("h", "help", false, "help");
|
||||||
|
options.getOption("h").setType(boolean.class);
|
||||||
|
|
||||||
|
|
||||||
|
super.options = options;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@@ -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.app.bulkedit;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CLI variant for the {@link MetadataImport} class
|
||||||
|
* This has been made so that we can specify the behaviour of the determineChanges method to be specific for the CLI
|
||||||
|
*/
|
||||||
|
public class MetadataImportCLI extends MetadataImport {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean determineChange(DSpaceRunnableHandler handler) throws IOException {
|
||||||
|
handler.logInfo("Do you want to make these changes? [y/n] ");
|
||||||
|
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
|
||||||
|
String yn = bufferedReader.readLine();
|
||||||
|
if ("y".equalsIgnoreCase(yn)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkedit;
|
||||||
|
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ScriptConfiguration} for the {@link org.dspace.app.bulkedit.MetadataImportCLI} CLI script
|
||||||
|
*/
|
||||||
|
public class MetadataImportCliScriptConfiguration extends MetadataImportScriptConfiguration<MetadataImportCLI> {
|
||||||
|
}
|
@@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkedit;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ScriptConfiguration} for the {@link MetadataImport} script
|
||||||
|
*/
|
||||||
|
public class MetadataImportScriptConfiguration<T extends MetadataImport> extends ScriptConfiguration<T> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
private Class<T> dspaceRunnableClass;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getDspaceRunnableClass() {
|
||||||
|
return dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the dspaceRunnableClass
|
||||||
|
* @param dspaceRunnableClass The dspaceRunnableClass to be set on this MetadataImportScriptConfiguration
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
|
||||||
|
this.dspaceRunnableClass = dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowedToExecute(Context context) {
|
||||||
|
try {
|
||||||
|
return authorizeService.isAdmin(context);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("SQLException occurred when checking if the current user is an admin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Options getOptions() {
|
||||||
|
if (options == null) {
|
||||||
|
Options options = new Options();
|
||||||
|
|
||||||
|
options.addOption("f", "file", true, "source file");
|
||||||
|
options.getOption("f").setType(InputStream.class);
|
||||||
|
options.getOption("f").setRequired(true);
|
||||||
|
options.addOption("e", "email", true, "email address or user id of user (required if adding new items)");
|
||||||
|
options.getOption("e").setType(String.class);
|
||||||
|
options.getOption("e").setRequired(true);
|
||||||
|
options.addOption("s", "silent", false,
|
||||||
|
"silent operation - doesn't request confirmation of changes USE WITH CAUTION");
|
||||||
|
options.getOption("s").setType(boolean.class);
|
||||||
|
options.addOption("w", "workflow", false, "workflow - when adding new items, use collection workflow");
|
||||||
|
options.getOption("w").setType(boolean.class);
|
||||||
|
options.addOption("n", "notify", false,
|
||||||
|
"notify - when adding new items using a workflow, send notification emails");
|
||||||
|
options.getOption("n").setType(boolean.class);
|
||||||
|
options.addOption("v", "validate-only", false,
|
||||||
|
"validate - just validate the csv, don't run the import");
|
||||||
|
options.getOption("v").setType(boolean.class);
|
||||||
|
options.addOption("t", "template", false,
|
||||||
|
"template - when adding new items, use the collection template (if it exists)");
|
||||||
|
options.getOption("t").setType(boolean.class);
|
||||||
|
options.addOption("h", "help", false, "help");
|
||||||
|
options.getOption("h").setType(boolean.class);
|
||||||
|
|
||||||
|
super.options = options;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
}
|
@@ -16,9 +16,11 @@ import java.util.TreeMap;
|
|||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.dspace.scripts.DSpaceRunnable;
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
import org.dspace.scripts.factory.ScriptServiceFactory;
|
import org.dspace.scripts.factory.ScriptServiceFactory;
|
||||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
import org.dspace.scripts.handler.impl.CommandLineDSpaceRunnableHandler;
|
import org.dspace.scripts.handler.impl.CommandLineDSpaceRunnableHandler;
|
||||||
|
import org.dspace.scripts.service.ScriptService;
|
||||||
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;
|
||||||
@@ -44,7 +46,8 @@ public class ScriptLauncher {
|
|||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
*/
|
*/
|
||||||
private ScriptLauncher() { }
|
private ScriptLauncher() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the DSpace script launcher
|
* Execute the DSpace script launcher
|
||||||
@@ -54,7 +57,7 @@ public class ScriptLauncher {
|
|||||||
* @throws FileNotFoundException if file doesn't exist
|
* @throws FileNotFoundException if file doesn't exist
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
throws FileNotFoundException, IOException {
|
throws FileNotFoundException, IOException, IllegalAccessException, InstantiationException {
|
||||||
// Initialise the service manager kernel
|
// Initialise the service manager kernel
|
||||||
try {
|
try {
|
||||||
kernelImpl = DSpaceKernelInit.getKernel(null);
|
kernelImpl = DSpaceKernelInit.getKernel(null);
|
||||||
@@ -107,13 +110,18 @@ public class ScriptLauncher {
|
|||||||
* @param commandConfigs The Document
|
* @param commandConfigs The Document
|
||||||
* @param dSpaceRunnableHandler The DSpaceRunnableHandler for this execution
|
* @param dSpaceRunnableHandler The DSpaceRunnableHandler for this execution
|
||||||
* @param kernelImpl The relevant DSpaceKernelImpl
|
* @param kernelImpl The relevant DSpaceKernelImpl
|
||||||
* @return A 1 or 0 depending on whether the script failed or passed respectively
|
* @return A 1 or 0 depending on whether the script failed or passed respectively
|
||||||
*/
|
*/
|
||||||
public static int handleScript(String[] args, Document commandConfigs,
|
public static int handleScript(String[] args, Document commandConfigs,
|
||||||
DSpaceRunnableHandler dSpaceRunnableHandler,
|
DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||||
DSpaceKernelImpl kernelImpl) {
|
DSpaceKernelImpl kernelImpl) throws InstantiationException, IllegalAccessException {
|
||||||
int status;
|
int status;
|
||||||
DSpaceRunnable script = ScriptServiceFactory.getInstance().getScriptService().getScriptForName(args[0]);
|
ScriptService scriptService = ScriptServiceFactory.getInstance().getScriptService();
|
||||||
|
ScriptConfiguration scriptConfiguration = scriptService.getScriptConfiguration(args[0]);
|
||||||
|
DSpaceRunnable script = null;
|
||||||
|
if (scriptConfiguration != null) {
|
||||||
|
script = scriptService.createDSpaceRunnableForScriptConfiguration(scriptConfiguration);
|
||||||
|
}
|
||||||
if (script != null) {
|
if (script != null) {
|
||||||
status = executeScript(args, dSpaceRunnableHandler, script);
|
status = executeScript(args, dSpaceRunnableHandler, script);
|
||||||
} else {
|
} else {
|
||||||
@@ -127,12 +135,12 @@ public class ScriptLauncher {
|
|||||||
* @param args The arguments of the script with the script name as first place in the array
|
* @param args The arguments of the script with the script name as first place in the array
|
||||||
* @param dSpaceRunnableHandler The relevant DSpaceRunnableHandler
|
* @param dSpaceRunnableHandler The relevant DSpaceRunnableHandler
|
||||||
* @param script The script to be executed
|
* @param script The script to be executed
|
||||||
* @return A 1 or 0 depending on whether the script failed or passed respectively
|
* @return A 1 or 0 depending on whether the script failed or passed respectively
|
||||||
*/
|
*/
|
||||||
private static int executeScript(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
private static int executeScript(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||||
DSpaceRunnable script) {
|
DSpaceRunnable script) {
|
||||||
try {
|
try {
|
||||||
script.initialize(args, dSpaceRunnableHandler);
|
script.initialize(args, dSpaceRunnableHandler, null);
|
||||||
script.run();
|
script.run();
|
||||||
return 0;
|
return 0;
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
|
@@ -10,6 +10,7 @@ package org.dspace.app.util;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.dspace.core.Utils;
|
||||||
/**
|
/**
|
||||||
* Class representing all DC inputs required for a submission, organized into pages
|
* Class representing all DC inputs required for a submission, organized into pages
|
||||||
*
|
*
|
||||||
@@ -107,9 +108,21 @@ public class DCInputSet {
|
|||||||
for (int i = 0; i < inputs.length; i++) {
|
for (int i = 0; i < inputs.length; i++) {
|
||||||
for (int j = 0; j < inputs[i].length; j++) {
|
for (int j = 0; j < inputs[i].length; j++) {
|
||||||
DCInput field = inputs[i][j];
|
DCInput field = inputs[i][j];
|
||||||
String fullName = field.getFieldName();
|
// If this is a "qualdrop_value" field, then the full field name is the field + dropdown qualifier
|
||||||
if (fullName.equals(fieldName)) {
|
if (field.getInputType().equals("qualdrop_value")) {
|
||||||
return true;
|
List<String> pairs = field.getPairs();
|
||||||
|
for (int k = 0; k < pairs.size(); k += 2) {
|
||||||
|
String qualifier = pairs.get(k + 1);
|
||||||
|
String fullName = Utils.standardize(field.getSchema(), field.getElement(), qualifier, ".");
|
||||||
|
if (fullName.equals(fieldName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String fullName = field.getFieldName();
|
||||||
|
if (fullName.equals(fieldName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -250,12 +250,8 @@ public class IndexVersion {
|
|||||||
} else if (firstMinor > secondMinor) {
|
} else if (firstMinor > secondMinor) {
|
||||||
// If we get here, major versions must be EQUAL. Now, time to check our minor versions
|
// If we get here, major versions must be EQUAL. Now, time to check our minor versions
|
||||||
return GREATER_THAN;
|
return GREATER_THAN;
|
||||||
} else if (firstMinor < secondMinor) {
|
|
||||||
return LESS_THAN;
|
|
||||||
} else {
|
} else {
|
||||||
// This is an impossible scenario.
|
return LESS_THAN;
|
||||||
// This 'else' should never be triggered since we've checked for equality above already
|
|
||||||
return EQUAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.content;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterators;
|
||||||
|
import org.dspace.app.bulkedit.DSpaceCSV;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.content.service.MetadataDSpaceCsvExportService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.handle.factory.HandleServiceFactory;
|
||||||
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link MetadataDSpaceCsvExportService}
|
||||||
|
*/
|
||||||
|
public class MetadataDSpaceCsvExportServiceImpl implements MetadataDSpaceCsvExportService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ItemService itemService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean exportAllMetadata, String handle,
|
||||||
|
DSpaceRunnableHandler handler) throws Exception {
|
||||||
|
Iterator<Item> toExport = null;
|
||||||
|
|
||||||
|
if (exportAllItems) {
|
||||||
|
handler.logInfo("Exporting whole repository WARNING: May take some time!");
|
||||||
|
toExport = itemService.findAll(context);
|
||||||
|
} else {
|
||||||
|
DSpaceObject dso = HandleServiceFactory.getInstance().getHandleService().resolveToObject(context, handle);
|
||||||
|
if (dso == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Item '" + handle + "' does not resolve to an item in your repository!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dso.getType() == Constants.ITEM) {
|
||||||
|
handler.logInfo("Exporting item '" + dso.getName() + "' (" + handle + ")");
|
||||||
|
List<Item> item = new ArrayList<>();
|
||||||
|
item.add((Item) dso);
|
||||||
|
toExport = item.iterator();
|
||||||
|
} else if (dso.getType() == Constants.COLLECTION) {
|
||||||
|
handler.logInfo("Exporting collection '" + dso.getName() + "' (" + handle + ")");
|
||||||
|
Collection collection = (Collection) dso;
|
||||||
|
toExport = itemService.findByCollection(context, collection);
|
||||||
|
} else if (dso.getType() == Constants.COMMUNITY) {
|
||||||
|
handler.logInfo("Exporting community '" + dso.getName() + "' (" + handle + ")");
|
||||||
|
toExport = buildFromCommunity(context, (Community) dso);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Error identifying '" + handle + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DSpaceCSV csv = this.export(context, toExport, exportAllMetadata);
|
||||||
|
return csv;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DSpaceCSV export(Context context, Iterator<Item> toExport, boolean exportAll) throws Exception {
|
||||||
|
Context.Mode originalMode = context.getCurrentMode();
|
||||||
|
context.setMode(Context.Mode.READ_ONLY);
|
||||||
|
|
||||||
|
// Process each item
|
||||||
|
DSpaceCSV csv = new DSpaceCSV(exportAll);
|
||||||
|
while (toExport.hasNext()) {
|
||||||
|
Item item = toExport.next();
|
||||||
|
csv.addItem(item);
|
||||||
|
context.uncacheEntity(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.setMode(originalMode);
|
||||||
|
// Return the results
|
||||||
|
return csv;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DSpaceCSV export(Context context, Community community, boolean exportAll) throws Exception {
|
||||||
|
return export(context, buildFromCommunity(context, community), exportAll);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an array list of item ids that are in a community (include sub-communities and collections)
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param community The community to build from
|
||||||
|
* @return The list of item ids
|
||||||
|
* @throws SQLException if database error
|
||||||
|
*/
|
||||||
|
private Iterator<Item> buildFromCommunity(Context context, Community community)
|
||||||
|
throws SQLException {
|
||||||
|
// Add all the collections
|
||||||
|
List<Collection> collections = community.getCollections();
|
||||||
|
Iterator<Item> result = null;
|
||||||
|
for (Collection collection : collections) {
|
||||||
|
Iterator<Item> items = itemService.findByCollection(context, collection);
|
||||||
|
result = addItemsToResult(result, items);
|
||||||
|
|
||||||
|
}
|
||||||
|
// Add all the sub-communities
|
||||||
|
List<Community> communities = community.getSubcommunities();
|
||||||
|
for (Community subCommunity : communities) {
|
||||||
|
Iterator<Item> items = buildFromCommunity(context, subCommunity);
|
||||||
|
result = addItemsToResult(result, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Iterator<Item> addItemsToResult(Iterator<Item> result, Iterator<Item> items) {
|
||||||
|
if (result == null) {
|
||||||
|
result = items;
|
||||||
|
} else {
|
||||||
|
result = Iterators.concat(result, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.content.service;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.dspace.app.bulkedit.DSpaceCSV;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the interface to be implemented by a Service that deals with the exporting of Metadata
|
||||||
|
*/
|
||||||
|
public interface MetadataDSpaceCsvExportService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will export DSpaceObject objects depending on the parameters it gets. It can export all the items
|
||||||
|
* in the repository, all the items in a community, all the items in a collection or a specific item. The latter
|
||||||
|
* three are specified by the handle parameter. The entire repository can be exported by defining the
|
||||||
|
* exportAllItems parameter as true
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param exportAllItems A boolean indicating whether or not the entire repository should be exported
|
||||||
|
* @param exportAllMetadata Defines if all metadata should be exported or only the allowed ones
|
||||||
|
* @param handle The handle for the DSpaceObject to be exported, can be a Community, Collection or Item
|
||||||
|
* @return A DSpaceCSV object containing the exported information
|
||||||
|
* @throws Exception If something goes wrong
|
||||||
|
*/
|
||||||
|
public DSpaceCSV handleExport(Context context, boolean exportAllItems, boolean exportAllMetadata,
|
||||||
|
String handle, DSpaceRunnableHandler dSpaceRunnableHandler) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will export all the Items in the given toExport iterator to a DSpaceCSV
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param toExport The iterator containing the items to export
|
||||||
|
* @param exportAll Defines if all metadata should be exported or only the allowed ones
|
||||||
|
* @return A DSpaceCSV object containing the exported information
|
||||||
|
* @throws Exception If something goes wrong
|
||||||
|
*/
|
||||||
|
public DSpaceCSV export(Context context, Iterator<Item> toExport, boolean exportAll) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will export all the Items within the given Community to a DSpaceCSV
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param community The Community that contains the Items to be exported
|
||||||
|
* @param exportAll Defines if all metadata should be exported or only the allowed ones
|
||||||
|
* @return A DSpaceCSV object containing the exported information
|
||||||
|
* @throws Exception If something goes wrong
|
||||||
|
*/
|
||||||
|
public DSpaceCSV export(Context context, Community community, boolean exportAll) throws Exception;
|
||||||
|
|
||||||
|
}
|
@@ -14,7 +14,6 @@ import java.util.Optional;
|
|||||||
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.Options;
|
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.content.Community;
|
import org.dspace.content.Community;
|
||||||
@@ -30,17 +29,18 @@ import org.dspace.discovery.indexobject.factory.IndexFactory;
|
|||||||
import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory;
|
import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory;
|
||||||
import org.dspace.handle.factory.HandleServiceFactory;
|
import org.dspace.handle.factory.HandleServiceFactory;
|
||||||
import org.dspace.scripts.DSpaceRunnable;
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to reindex dspace communities/collections/items into discovery
|
* Class used to reindex dspace communities/collections/items into discovery
|
||||||
*/
|
*/
|
||||||
public class IndexClient extends DSpaceRunnable {
|
public class IndexClient extends DSpaceRunnable<IndexDiscoveryScriptConfiguration> {
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
|
private IndexingService indexer = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||||
@Autowired
|
.getServiceByName(IndexingService.class.getName(),
|
||||||
private IndexingService indexer;
|
IndexingService.class);
|
||||||
|
|
||||||
private IndexClientOptions indexClientOptions;
|
private IndexClientOptions indexClientOptions;
|
||||||
|
|
||||||
@@ -144,6 +144,12 @@ public class IndexClient extends DSpaceRunnable {
|
|||||||
handler.logInfo("Done with indexing");
|
handler.logInfo("Done with indexing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IndexDiscoveryScriptConfiguration getScriptConfiguration() {
|
||||||
|
return new DSpace().getServiceManager().getServiceByName("index-discovery",
|
||||||
|
IndexDiscoveryScriptConfiguration.class);
|
||||||
|
}
|
||||||
|
|
||||||
public void setup() throws ParseException {
|
public void setup() throws ParseException {
|
||||||
try {
|
try {
|
||||||
context = new Context(Context.Mode.READ_ONLY);
|
context = new Context(Context.Mode.READ_ONLY);
|
||||||
@@ -151,18 +157,8 @@ public class IndexClient extends DSpaceRunnable {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ParseException("Unable to create a new DSpace Context: " + e.getMessage());
|
throw new ParseException("Unable to create a new DSpace Context: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
indexClientOptions = IndexClientOptions.getIndexClientOption(commandLine);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indexes the given object and all children, if applicable.
|
* Indexes the given object and all children, if applicable.
|
||||||
*
|
*
|
||||||
|
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.discovery;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ScriptConfiguration} for the {@link IndexClient} script
|
||||||
|
*/
|
||||||
|
public class IndexDiscoveryScriptConfiguration<T extends IndexClient> extends ScriptConfiguration<T> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
private Class<T> dspaceRunnableClass;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getDspaceRunnableClass() {
|
||||||
|
return dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowedToExecute(Context context) {
|
||||||
|
try {
|
||||||
|
return authorizeService.isAdmin(context);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("SQLException occurred when checking if the current user is an admin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Options getOptions() {
|
||||||
|
if (options == null) {
|
||||||
|
super.options = IndexClientOptions.constructOptions();
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the dspaceRunnableClass
|
||||||
|
* @param dspaceRunnableClass The dspaceRunnableClass to be set on this IndexDiscoveryScriptConfiguration
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
|
||||||
|
this.dspaceRunnableClass = dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
}
|
@@ -8,6 +8,8 @@
|
|||||||
package org.dspace.license;
|
package org.dspace.license;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author wbossons
|
* @author wbossons
|
||||||
*/
|
*/
|
||||||
@@ -15,17 +17,17 @@ public class CCLicense {
|
|||||||
|
|
||||||
private String licenseName;
|
private String licenseName;
|
||||||
private String licenseId;
|
private String licenseId;
|
||||||
private int order = 0;
|
private List<CCLicenseField> ccLicenseFieldList;
|
||||||
|
|
||||||
public CCLicense() {
|
public CCLicense() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CCLicense(String licenseId, String licenseName, int order) {
|
public CCLicense(String licenseId, String licenseName, List<CCLicenseField> ccLicenseFieldList) {
|
||||||
super();
|
super();
|
||||||
this.licenseId = licenseId;
|
this.licenseId = licenseId;
|
||||||
this.licenseName = licenseName;
|
this.licenseName = licenseName;
|
||||||
this.order = order;
|
this.ccLicenseFieldList = ccLicenseFieldList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLicenseName() {
|
public String getLicenseName() {
|
||||||
@@ -44,13 +46,19 @@ public class CCLicense {
|
|||||||
this.licenseId = licenseId;
|
this.licenseId = licenseId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOrder() {
|
/**
|
||||||
return this.order;
|
* Gets the list of CC License Fields
|
||||||
|
* @return the list of CC License Fields
|
||||||
|
*/
|
||||||
|
public List<CCLicenseField> getCcLicenseFieldList() {
|
||||||
|
return ccLicenseFieldList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOrder(int order) {
|
/**
|
||||||
this.order = order;
|
* Sets the list of CC License Fields
|
||||||
|
* @param ccLicenseFieldList
|
||||||
|
*/
|
||||||
|
public void setCcLicenseFieldList(final List<CCLicenseField> ccLicenseFieldList) {
|
||||||
|
this.ccLicenseFieldList = ccLicenseFieldList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* 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.license;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jdom.Document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service interface class for the Creative commons license connector service.
|
||||||
|
* The implementation of this class is responsible for all the calls to the CC license API and parsing the response
|
||||||
|
* The service is autowired by spring
|
||||||
|
*/
|
||||||
|
public interface CCLicenseConnectorService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the CC Licenses for the provided language from the CC License API
|
||||||
|
*
|
||||||
|
* @param language - the language to retrieve the licenses for
|
||||||
|
* @return a map of licenses with the id and the license for the provided language
|
||||||
|
*/
|
||||||
|
public Map<String, CCLicense> retrieveLicenses(String language);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CC License URI based on the provided license id, language and answers to the field questions from
|
||||||
|
* the CC License API
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to retrieve the full answerMap
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the CC License URI
|
||||||
|
*/
|
||||||
|
public String retrieveRightsByQuestion(String licenseId,
|
||||||
|
String language,
|
||||||
|
Map<String, String> answerMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the license RDF document based on the license URI
|
||||||
|
*
|
||||||
|
* @param licenseURI - The license URI for which to retrieve the license RDF document
|
||||||
|
* @return the license RDF document
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public Document retrieveLicenseRDFDoc(String licenseURI) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the license Name from the license document
|
||||||
|
*
|
||||||
|
* @param doc - The license document from which to retrieve the license name
|
||||||
|
* @return the license name
|
||||||
|
*/
|
||||||
|
public String retrieveLicenseName(final Document doc);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,371 @@
|
|||||||
|
/**
|
||||||
|
* 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.license;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.jaxen.JaxenException;
|
||||||
|
import org.jaxen.jdom.JDOMXPath;
|
||||||
|
import org.jdom.Attribute;
|
||||||
|
import org.jdom.Document;
|
||||||
|
import org.jdom.Element;
|
||||||
|
import org.jdom.JDOMException;
|
||||||
|
import org.jdom.input.SAXBuilder;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation for the Creative commons license connector service.
|
||||||
|
* This class is responsible for all the calls to the CC license API and parsing the response
|
||||||
|
*/
|
||||||
|
public class CCLicenseConnectorServiceImpl implements CCLicenseConnectorService, InitializingBean {
|
||||||
|
|
||||||
|
private Logger log = org.apache.logging.log4j.LogManager.getLogger(CCLicenseConnectorServiceImpl.class);
|
||||||
|
|
||||||
|
private CloseableHttpClient client;
|
||||||
|
protected SAXBuilder parser = new SAXBuilder();
|
||||||
|
|
||||||
|
private String postArgument = "answers";
|
||||||
|
private String postAnswerFormat =
|
||||||
|
"<answers> " +
|
||||||
|
"<locale>{1}</locale>" +
|
||||||
|
"<license-{0}>" +
|
||||||
|
"{2}" +
|
||||||
|
"</license-{0}>" +
|
||||||
|
"</answers>";
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
|
||||||
|
client = builder
|
||||||
|
.disableAutomaticRetries()
|
||||||
|
.setMaxConnTotal(5)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the CC Licenses for the provided language from the CC License API
|
||||||
|
*
|
||||||
|
* @param language - the language to retrieve the licenses for
|
||||||
|
* @return a map of licenses with the id and the license for the provided language
|
||||||
|
*/
|
||||||
|
public Map<String, CCLicense> retrieveLicenses(String language) {
|
||||||
|
String ccLicenseUrl = configurationService.getProperty("cc.api.rooturl");
|
||||||
|
|
||||||
|
String uri = ccLicenseUrl + "/?locale=" + language;
|
||||||
|
HttpGet httpGet = new HttpGet(uri);
|
||||||
|
|
||||||
|
List<String> licenses;
|
||||||
|
try (CloseableHttpResponse response = client.execute(httpGet)) {
|
||||||
|
licenses = retrieveLicenses(response);
|
||||||
|
} catch (JDOMException | JaxenException | IOException e) {
|
||||||
|
log.error("Error while retrieving the license details using url: " + uri, e);
|
||||||
|
licenses = Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, CCLicense> ccLicenses = new HashMap<>();
|
||||||
|
|
||||||
|
for (String license : licenses) {
|
||||||
|
|
||||||
|
String licenseUri = ccLicenseUrl + "/license/" + license;
|
||||||
|
HttpGet licenseHttpGet = new HttpGet(licenseUri);
|
||||||
|
try (CloseableHttpResponse response = client.execute(licenseHttpGet)) {
|
||||||
|
CCLicense ccLicense = retrieveLicenseObject(license, response);
|
||||||
|
ccLicenses.put(ccLicense.getLicenseId(), ccLicense);
|
||||||
|
} catch (JaxenException | JDOMException | IOException e) {
|
||||||
|
log.error("Error while retrieving the license details using url: " + licenseUri, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ccLicenses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the list of licenses from the response from the CC License API and remove the licenses configured
|
||||||
|
* to be excluded
|
||||||
|
*
|
||||||
|
* @param response The response from the API
|
||||||
|
* @return a list of license identifiers for which details need to be retrieved
|
||||||
|
* @throws IOException
|
||||||
|
* @throws JaxenException
|
||||||
|
* @throws JDOMException
|
||||||
|
*/
|
||||||
|
private List<String> retrieveLicenses(CloseableHttpResponse response)
|
||||||
|
throws IOException, JaxenException, JDOMException {
|
||||||
|
|
||||||
|
List<String> domains = new LinkedList<>();
|
||||||
|
String[] excludedLicenses = configurationService.getArrayProperty("cc.license.classfilter");
|
||||||
|
|
||||||
|
|
||||||
|
String responseString = EntityUtils.toString(response.getEntity());
|
||||||
|
JDOMXPath licenseClassXpath = new JDOMXPath("//licenses/license");
|
||||||
|
|
||||||
|
|
||||||
|
try (StringReader stringReader = new StringReader(responseString)) {
|
||||||
|
InputSource is = new InputSource(stringReader);
|
||||||
|
org.jdom.Document classDoc = this.parser.build(is);
|
||||||
|
|
||||||
|
List<Element> elements = licenseClassXpath.selectNodes(classDoc);
|
||||||
|
for (Element element : elements) {
|
||||||
|
String licenseId = getSingleNodeValue(element, "@id");
|
||||||
|
if (StringUtils.isNotBlank(licenseId) && !ArrayUtils.contains(excludedLicenses, licenseId)) {
|
||||||
|
domains.add(licenseId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return domains;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the response for a single CC License and return the corresponding CC License Object
|
||||||
|
*
|
||||||
|
* @param licenseId the license id of the CC License to retrieve
|
||||||
|
* @param response for a specific CC License response
|
||||||
|
* @return the corresponding CC License Object
|
||||||
|
* @throws IOException
|
||||||
|
* @throws JaxenException
|
||||||
|
* @throws JDOMException
|
||||||
|
*/
|
||||||
|
private CCLicense retrieveLicenseObject(final String licenseId, CloseableHttpResponse response)
|
||||||
|
throws IOException, JaxenException, JDOMException {
|
||||||
|
|
||||||
|
String responseString = EntityUtils.toString(response.getEntity());
|
||||||
|
|
||||||
|
|
||||||
|
JDOMXPath licenseClassXpath = new JDOMXPath("//licenseclass");
|
||||||
|
JDOMXPath licenseFieldXpath = new JDOMXPath("field");
|
||||||
|
|
||||||
|
|
||||||
|
try (StringReader stringReader = new StringReader(responseString)) {
|
||||||
|
InputSource is = new InputSource(stringReader);
|
||||||
|
|
||||||
|
org.jdom.Document classDoc = this.parser.build(is);
|
||||||
|
|
||||||
|
Object element = licenseClassXpath.selectSingleNode(classDoc);
|
||||||
|
String licenseLabel = getSingleNodeValue(element, "label");
|
||||||
|
|
||||||
|
List<CCLicenseField> ccLicenseFields = new LinkedList<>();
|
||||||
|
|
||||||
|
List<Element> licenseFields = licenseFieldXpath.selectNodes(element);
|
||||||
|
for (Element licenseField : licenseFields) {
|
||||||
|
CCLicenseField ccLicenseField = parseLicenseField(licenseField);
|
||||||
|
ccLicenseFields.add(ccLicenseField);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CCLicense(licenseId, licenseLabel, ccLicenseFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CCLicenseField parseLicenseField(final Element licenseField) throws JaxenException {
|
||||||
|
String id = getSingleNodeValue(licenseField, "@id");
|
||||||
|
String label = getSingleNodeValue(licenseField, "label");
|
||||||
|
String description = getSingleNodeValue(licenseField, "description");
|
||||||
|
|
||||||
|
JDOMXPath enumXpath = new JDOMXPath("enum");
|
||||||
|
List<Element> enums = enumXpath.selectNodes(licenseField);
|
||||||
|
|
||||||
|
List<CCLicenseFieldEnum> ccLicenseFieldEnumList = new LinkedList<>();
|
||||||
|
|
||||||
|
for (Element enumElement : enums) {
|
||||||
|
CCLicenseFieldEnum ccLicenseFieldEnum = parseEnum(enumElement);
|
||||||
|
ccLicenseFieldEnumList.add(ccLicenseFieldEnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CCLicenseField(id, label, description, ccLicenseFieldEnumList);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private CCLicenseFieldEnum parseEnum(final Element enumElement) throws JaxenException {
|
||||||
|
String id = getSingleNodeValue(enumElement, "@id");
|
||||||
|
String label = getSingleNodeValue(enumElement, "label");
|
||||||
|
String description = getSingleNodeValue(enumElement, "description");
|
||||||
|
|
||||||
|
return new CCLicenseFieldEnum(id, label, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getNodeValue(final Object el) {
|
||||||
|
if (el instanceof Element) {
|
||||||
|
return ((Element) el).getValue();
|
||||||
|
} else if (el instanceof Attribute) {
|
||||||
|
return ((Attribute) el).getValue();
|
||||||
|
} else if (el instanceof String) {
|
||||||
|
return (String) el;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSingleNodeValue(final Object t, String query) throws JaxenException {
|
||||||
|
JDOMXPath xpath = new JDOMXPath(query);
|
||||||
|
Object singleNode = xpath.selectSingleNode(t);
|
||||||
|
|
||||||
|
return getNodeValue(singleNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CC License URI based on the provided license id, language and answers to the field questions from
|
||||||
|
* the CC License API
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to retrieve the full answerMap
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the CC License URI
|
||||||
|
*/
|
||||||
|
public String retrieveRightsByQuestion(String licenseId,
|
||||||
|
String language,
|
||||||
|
Map<String, String> answerMap) {
|
||||||
|
|
||||||
|
String ccLicenseUrl = configurationService.getProperty("cc.api.rooturl");
|
||||||
|
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost(ccLicenseUrl + "/license/" + licenseId + "/issue");
|
||||||
|
|
||||||
|
|
||||||
|
String answers = createAnswerString(answerMap);
|
||||||
|
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||||
|
String text = MessageFormat.format(postAnswerFormat, licenseId, language, answers);
|
||||||
|
builder.addTextBody(postArgument, text);
|
||||||
|
|
||||||
|
HttpEntity multipart = builder.build();
|
||||||
|
|
||||||
|
httpPost.setEntity(multipart);
|
||||||
|
|
||||||
|
try (CloseableHttpResponse response = client.execute(httpPost)) {
|
||||||
|
return retrieveLicenseUri(response);
|
||||||
|
} catch (JDOMException | JaxenException | IOException e) {
|
||||||
|
log.error("Error while retrieving the license uri for license : " + licenseId + " with answers "
|
||||||
|
+ answerMap.toString(), e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the response for the CC License URI request and return the corresponding CC License URI
|
||||||
|
*
|
||||||
|
* @param response for a specific CC License URI response
|
||||||
|
* @return the corresponding CC License URI as a string
|
||||||
|
* @throws IOException
|
||||||
|
* @throws JaxenException
|
||||||
|
* @throws JDOMException
|
||||||
|
*/
|
||||||
|
private String retrieveLicenseUri(final CloseableHttpResponse response)
|
||||||
|
throws IOException, JaxenException, JDOMException {
|
||||||
|
|
||||||
|
String responseString = EntityUtils.toString(response.getEntity());
|
||||||
|
JDOMXPath licenseClassXpath = new JDOMXPath("//result/license-uri");
|
||||||
|
|
||||||
|
|
||||||
|
try (StringReader stringReader = new StringReader(responseString)) {
|
||||||
|
InputSource is = new InputSource(stringReader);
|
||||||
|
org.jdom.Document classDoc = this.parser.build(is);
|
||||||
|
|
||||||
|
Object node = licenseClassXpath.selectSingleNode(classDoc);
|
||||||
|
String nodeValue = getNodeValue(node);
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(nodeValue)) {
|
||||||
|
return nodeValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createAnswerString(final Map<String, String> parameterMap) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String key : parameterMap.keySet()) {
|
||||||
|
sb.append("<");
|
||||||
|
sb.append(key);
|
||||||
|
sb.append(">");
|
||||||
|
sb.append(parameterMap.get(key));
|
||||||
|
sb.append("</");
|
||||||
|
sb.append(key);
|
||||||
|
sb.append(">");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the license RDF document based on the license URI
|
||||||
|
*
|
||||||
|
* @param licenseURI - The license URI for which to retrieve the license RDF document
|
||||||
|
* @return the license RDF document
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Document retrieveLicenseRDFDoc(String licenseURI) throws IOException {
|
||||||
|
String ccLicenseUrl = configurationService.getProperty("cc.api.rooturl");
|
||||||
|
|
||||||
|
String issueUrl = ccLicenseUrl + "/details?license-uri=" + licenseURI;
|
||||||
|
|
||||||
|
URL request_url;
|
||||||
|
try {
|
||||||
|
request_url = new URL(issueUrl);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
URLConnection connection = request_url.openConnection();
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
try {
|
||||||
|
// parsing document from input stream
|
||||||
|
InputStream stream = connection.getInputStream();
|
||||||
|
Document doc = parser.build(stream);
|
||||||
|
return doc;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error while retrieving the license document for URI: " + licenseURI, e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the license Name from the license document
|
||||||
|
*
|
||||||
|
* @param doc - The license document from which to retrieve the license name
|
||||||
|
* @return the license name
|
||||||
|
*/
|
||||||
|
public String retrieveLicenseName(final Document doc) {
|
||||||
|
try {
|
||||||
|
return getSingleNodeValue(doc, "//result/license-name");
|
||||||
|
} catch (JaxenException e) {
|
||||||
|
log.error("Error while retrieving the license name from the license document", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -7,8 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.license;
|
package org.dspace.license;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class for representation of a license field declaration.
|
* Wrapper class for representation of a license field declaration.
|
||||||
@@ -22,7 +21,7 @@ public class CCLicenseField {
|
|||||||
private String description = "";
|
private String description = "";
|
||||||
private String type = "";
|
private String type = "";
|
||||||
|
|
||||||
private HashMap fieldEnum = null;
|
private List<CCLicenseFieldEnum> fieldEnum = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new LicenseField class. Note that after construction,
|
* Construct a new LicenseField class. Note that after construction,
|
||||||
@@ -31,13 +30,11 @@ public class CCLicenseField {
|
|||||||
* @param id The unique identifier for this field; this value will be used in constructing the answers XML.
|
* @param id The unique identifier for this field; this value will be used in constructing the answers XML.
|
||||||
* @param label The label to use when generating the user interface.
|
* @param label The label to use when generating the user interface.
|
||||||
*/
|
*/
|
||||||
public CCLicenseField(String id, String label) {
|
public CCLicenseField(String id, String label, String description, List<CCLicenseFieldEnum> fieldEnum) {
|
||||||
super();
|
|
||||||
|
|
||||||
this.fieldEnum = new HashMap();
|
|
||||||
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
this.description = description;
|
||||||
|
this.fieldEnum = fieldEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,16 +87,12 @@ public class CCLicenseField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns an instance implementing the Map interface;
|
* Returns the list of enums of this field
|
||||||
* the instance contains a mapping from identifiers to
|
* @return the list of enums of this field
|
||||||
* labels for the enumeration values.
|
|
||||||
* @see Map
|
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getEnum() {
|
public List<CCLicenseFieldEnum> getFieldEnum() {
|
||||||
return this.fieldEnum;
|
return fieldEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.license;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class for representation of a license field enum declaration.
|
||||||
|
* A field enum is a single "answer" to the field question
|
||||||
|
*/
|
||||||
|
public class CCLicenseFieldEnum {
|
||||||
|
|
||||||
|
private String id = "";
|
||||||
|
private String label = "";
|
||||||
|
private String description = "";
|
||||||
|
|
||||||
|
public CCLicenseFieldEnum(String id, String label, String description) {
|
||||||
|
if (StringUtils.isNotBlank(id)) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(label)) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(description)) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the id of this enum
|
||||||
|
* @return the id of this enum
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the id of this enum
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
public void setId(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the label of this enum
|
||||||
|
* @return the label of this enum
|
||||||
|
*/
|
||||||
|
public String getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the label of this enum
|
||||||
|
* @param label
|
||||||
|
*/
|
||||||
|
public void setLabel(final String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the description of this enum
|
||||||
|
* @return the description of this enum
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the description of this enum
|
||||||
|
* @param description
|
||||||
|
*/
|
||||||
|
public void setDescription(final String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,435 +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.license;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.dspace.license.factory.LicenseServiceFactory;
|
|
||||||
import org.dspace.license.service.CreativeCommonsService;
|
|
||||||
import org.dspace.services.ConfigurationService;
|
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
|
||||||
import org.jaxen.JaxenException;
|
|
||||||
import org.jaxen.jdom.JDOMXPath;
|
|
||||||
import org.jdom.Attribute;
|
|
||||||
import org.jdom.Document;
|
|
||||||
import org.jdom.Element;
|
|
||||||
import org.jdom.JDOMException;
|
|
||||||
import org.jdom.input.SAXBuilder;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper around Creative Commons REST web services.
|
|
||||||
*
|
|
||||||
* @author Wendy Bossons
|
|
||||||
*/
|
|
||||||
public class CCLookup {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* log4j logger
|
|
||||||
*/
|
|
||||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(CCLookup.class);
|
|
||||||
|
|
||||||
private String cc_root;
|
|
||||||
private String jurisdiction;
|
|
||||||
private List<String> lcFilter = new ArrayList<String>();
|
|
||||||
|
|
||||||
private Document license_doc = null;
|
|
||||||
private String rdfString = null;
|
|
||||||
private String errorMessage = null;
|
|
||||||
private boolean success = false;
|
|
||||||
|
|
||||||
private SAXBuilder parser = new SAXBuilder();
|
|
||||||
private List<CCLicense> licenses = new ArrayList<CCLicense>();
|
|
||||||
private List<CCLicenseField> licenseFields = new ArrayList<CCLicenseField>();
|
|
||||||
|
|
||||||
protected CreativeCommonsService creativeCommonsService = LicenseServiceFactory.getInstance()
|
|
||||||
.getCreativeCommonsService();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new instance with the default web services root.
|
|
||||||
*/
|
|
||||||
public CCLookup() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
|
||||||
|
|
||||||
cc_root = configurationService.getProperty("cc.api.rooturl");
|
|
||||||
|
|
||||||
String jurisProp = configurationService.getProperty("cc.license.jurisdiction");
|
|
||||||
jurisdiction = (jurisProp != null) ? jurisProp : "";
|
|
||||||
|
|
||||||
String[] filters = configurationService.getArrayProperty("cc.license.classfilter");
|
|
||||||
if (filters != null) {
|
|
||||||
for (String name : filters) {
|
|
||||||
lcFilter.add(name.trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the id for a particular CCLicense label. Returns an
|
|
||||||
* empty string if no match is found.
|
|
||||||
*
|
|
||||||
* @param class_label The CCLicense label to find.
|
|
||||||
* @return Returns a String containing the License class ID if the label
|
|
||||||
* is found; if not found, returns an empty string.
|
|
||||||
* @see CCLicense
|
|
||||||
*/
|
|
||||||
public String getLicenseId(String class_label) {
|
|
||||||
for (int i = 0; i < this.licenses.size(); i++) {
|
|
||||||
if (((CCLicense) this.licenses.get(i)).getLicenseName().equals(class_label)) {
|
|
||||||
return ((CCLicense) this.licenses.get(i)).getLicenseId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries the web service for the available licenses.
|
|
||||||
*
|
|
||||||
* @param language The language to request labels and description strings in.
|
|
||||||
* @return Returns a Map of CCLicense objects.
|
|
||||||
* @see Map
|
|
||||||
* @see CCLicense
|
|
||||||
*/
|
|
||||||
public Collection<CCLicense> getLicenses(String language) {
|
|
||||||
|
|
||||||
// create XPath expressions
|
|
||||||
try {
|
|
||||||
JDOMXPath xp_Licenses = new JDOMXPath("//licenses/license");
|
|
||||||
JDOMXPath xp_LicenseID = new JDOMXPath("@id");
|
|
||||||
URL classUrl = new URL(this.cc_root + "/?locale=" + language);
|
|
||||||
Document classDoc = this.parser.build(classUrl);
|
|
||||||
// extract the identifiers and labels using XPath
|
|
||||||
List<Element> results = xp_Licenses.selectNodes(classDoc);
|
|
||||||
// populate licenses container
|
|
||||||
this.licenses.clear();
|
|
||||||
for (int i = 0; i < results.size(); i++) {
|
|
||||||
Element license = results.get(i);
|
|
||||||
// add if not filtered
|
|
||||||
String liD = ((Attribute) xp_LicenseID.selectSingleNode(license)).getValue();
|
|
||||||
if (!lcFilter.contains(liD)) {
|
|
||||||
this.licenses.add(new CCLicense(liD, license.getText(), i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JaxenException jaxen_e) {
|
|
||||||
return null;
|
|
||||||
} catch (JDOMException jdom_e) {
|
|
||||||
return null;
|
|
||||||
} catch (IOException io_e) {
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
// do nothing... but we should
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return licenses;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries the web service for a set of licenseFields for a particular license class.
|
|
||||||
*
|
|
||||||
* @param license A String specifying the CCLicense identifier to
|
|
||||||
* retrieve fields for.
|
|
||||||
* @param language the locale string
|
|
||||||
* @return A Collection of LicenseField objects.
|
|
||||||
* @see CCLicense
|
|
||||||
*/
|
|
||||||
public Collection<CCLicenseField> getLicenseFields(String license, String language) {
|
|
||||||
|
|
||||||
JDOMXPath xp_LicenseField;
|
|
||||||
JDOMXPath xp_LicenseID;
|
|
||||||
JDOMXPath xp_FieldType;
|
|
||||||
JDOMXPath xp_Description;
|
|
||||||
JDOMXPath xp_Label;
|
|
||||||
JDOMXPath xp_Enum;
|
|
||||||
|
|
||||||
Document fieldDoc;
|
|
||||||
|
|
||||||
URL classUrl;
|
|
||||||
List results = null;
|
|
||||||
List enumOptions = null;
|
|
||||||
|
|
||||||
// create XPath expressions
|
|
||||||
try {
|
|
||||||
xp_LicenseField = new JDOMXPath("//field");
|
|
||||||
xp_LicenseID = new JDOMXPath("@id");
|
|
||||||
xp_Description = new JDOMXPath("description");
|
|
||||||
xp_Label = new JDOMXPath("label");
|
|
||||||
xp_FieldType = new JDOMXPath("type");
|
|
||||||
xp_Enum = new JDOMXPath("enum");
|
|
||||||
|
|
||||||
} catch (JaxenException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve and parse the license class document
|
|
||||||
try {
|
|
||||||
classUrl = new URL(this.cc_root + "/license/" + license + "?locale=" + language);
|
|
||||||
} catch (Exception err) {
|
|
||||||
// do nothing... but we should
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse the licenses document
|
|
||||||
try {
|
|
||||||
fieldDoc = this.parser.build(classUrl);
|
|
||||||
} catch (JDOMException e) {
|
|
||||||
return null;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset the field definition container
|
|
||||||
this.licenseFields.clear();
|
|
||||||
|
|
||||||
// extract the identifiers and labels using XPath
|
|
||||||
try {
|
|
||||||
results = xp_LicenseField.selectNodes(fieldDoc);
|
|
||||||
} catch (JaxenException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < results.size(); i++) {
|
|
||||||
Element field = (Element) results.get(i);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// create the field object
|
|
||||||
CCLicenseField cclicensefield = new CCLicenseField(
|
|
||||||
((Attribute) xp_LicenseID.selectSingleNode(field)).getValue(),
|
|
||||||
((Element) xp_Label.selectSingleNode(field)).getText());
|
|
||||||
|
|
||||||
// extract additional properties
|
|
||||||
cclicensefield.setDescription(((Element) xp_Description.selectSingleNode(field)).getText());
|
|
||||||
cclicensefield.setType(((Element) xp_FieldType.selectSingleNode(field)).getText());
|
|
||||||
|
|
||||||
enumOptions = xp_Enum.selectNodes(field);
|
|
||||||
|
|
||||||
for (int j = 0; j < enumOptions.size(); j++) {
|
|
||||||
String id = ((Attribute) xp_LicenseID.selectSingleNode(enumOptions.get(j))).getValue();
|
|
||||||
String label = ((Element) xp_Label.selectSingleNode(enumOptions.get(j))).getText();
|
|
||||||
|
|
||||||
cclicensefield.getEnum().put(id, label);
|
|
||||||
|
|
||||||
} // for each enum option
|
|
||||||
|
|
||||||
this.licenseFields.add(cclicensefield);
|
|
||||||
} catch (JaxenException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return licenseFields;
|
|
||||||
} // licenseFields
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Passes a set of "answers" to the web service and retrieves a license.
|
|
||||||
*
|
|
||||||
* @param licenseId The identifier of the license class being requested.
|
|
||||||
* @param answers A Map containing the answers to the license fields;
|
|
||||||
* each key is the identifier of a LicenseField, with the value
|
|
||||||
* containing the user-supplied answer.
|
|
||||||
* @param lang The language to request localized elements in.
|
|
||||||
* @throws IOException if IO error
|
|
||||||
* @see CCLicense
|
|
||||||
* @see Map
|
|
||||||
*/
|
|
||||||
public void issue(String licenseId, Map answers, String lang)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
// Determine the issue URL
|
|
||||||
String issueUrl = this.cc_root + "/license/" + licenseId + "/issue";
|
|
||||||
// Assemble the "answers" document
|
|
||||||
String answer_doc = "<answers>\n<locale>" + lang + "</locale>\n" + "<license-" + licenseId + ">\n";
|
|
||||||
Iterator keys = answers.keySet().iterator();
|
|
||||||
|
|
||||||
try {
|
|
||||||
String current = (String) keys.next();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
answer_doc += "<" + current + ">" + (String) answers.get(current) + "</" + current + ">\n";
|
|
||||||
current = (String) keys.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (NoSuchElementException e) {
|
|
||||||
// exception indicates we've iterated through the
|
|
||||||
// entire collection; just swallow and continue
|
|
||||||
}
|
|
||||||
// answer_doc += "<jurisdiction></jurisidiction>\n"; FAILS with jurisdiction argument
|
|
||||||
answer_doc += "</license-" + licenseId + ">\n</answers>\n";
|
|
||||||
String post_data;
|
|
||||||
|
|
||||||
try {
|
|
||||||
post_data = URLEncoder.encode("answers", "UTF-8") + "=" + URLEncoder.encode(answer_doc, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
URL post_url;
|
|
||||||
try {
|
|
||||||
post_url = new URL(issueUrl);
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
URLConnection connection = post_url.openConnection();
|
|
||||||
// this will not be needed after I'm done TODO: remove
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
|
|
||||||
writer.write(post_data);
|
|
||||||
writer.flush();
|
|
||||||
// end TODO
|
|
||||||
try {
|
|
||||||
// parsing document from input stream
|
|
||||||
java.io.InputStream stream = connection.getInputStream();
|
|
||||||
this.license_doc = this.parser.build(stream);
|
|
||||||
} catch (JDOMException jde) {
|
|
||||||
log.warn(jde.getMessage());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn(e.getCause());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} // issue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Passes a set of "answers" to the web service and retrieves a license.
|
|
||||||
*
|
|
||||||
* @param licenseURI The uri of the license.
|
|
||||||
*
|
|
||||||
* Note: does not support localization in 1.5 -- not yet
|
|
||||||
* @throws IOException if IO error
|
|
||||||
* @see CCLicense
|
|
||||||
* @see Map
|
|
||||||
*/
|
|
||||||
public void issue(String licenseURI)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
// Determine the issue URL
|
|
||||||
// Example: http://api.creativecommons.org/rest/1.5/details?
|
|
||||||
// license-uri=http://creativecommons.org/licenses/by-nc-sa/3.0/
|
|
||||||
String issueUrl = cc_root + "/details?license-uri=" + licenseURI;
|
|
||||||
|
|
||||||
URL request_url;
|
|
||||||
try {
|
|
||||||
request_url = new URL(issueUrl);
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
URLConnection connection = request_url.openConnection();
|
|
||||||
// this will not be needed after I'm done TODO: remove
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
try {
|
|
||||||
// parsing document from input stream
|
|
||||||
java.io.InputStream stream = connection.getInputStream();
|
|
||||||
license_doc = this.parser.build(stream);
|
|
||||||
} catch (JDOMException jde) {
|
|
||||||
log.warn(jde.getMessage());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn(e.getCause());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} // issue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the URI for the license issued.
|
|
||||||
*
|
|
||||||
* @return A String containing the URI for the license issued.
|
|
||||||
*/
|
|
||||||
public String getLicenseUrl() {
|
|
||||||
String text = null;
|
|
||||||
try {
|
|
||||||
JDOMXPath xp_LicenseName = new JDOMXPath("//result/license-uri");
|
|
||||||
text = ((Element) xp_LicenseName.selectSingleNode(this.license_doc)).getText();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn(e.getMessage());
|
|
||||||
setSuccess(false);
|
|
||||||
text = "An error occurred getting the license - uri.";
|
|
||||||
} finally {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
} // getLicenseUrl
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the human readable name for the license issued.
|
|
||||||
*
|
|
||||||
* @return A String containing the license name.
|
|
||||||
*/
|
|
||||||
public String getLicenseName() {
|
|
||||||
String text = null;
|
|
||||||
try {
|
|
||||||
JDOMXPath xp_LicenseName = new JDOMXPath("//result/license-name");
|
|
||||||
text = ((Element) xp_LicenseName.selectSingleNode(this.license_doc)).getText();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn(e.getMessage());
|
|
||||||
setSuccess(false);
|
|
||||||
text = "An error occurred on the license name.";
|
|
||||||
} finally {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
} // getLicenseName
|
|
||||||
|
|
||||||
|
|
||||||
public org.jdom.Document getLicenseDocument() {
|
|
||||||
return this.license_doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRdf()
|
|
||||||
throws IOException {
|
|
||||||
String result = "";
|
|
||||||
try {
|
|
||||||
result = creativeCommonsService.fetchLicenseRDF(license_doc);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("An error occurred getting the rdf . . ." + e.getMessage());
|
|
||||||
setSuccess(false);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSuccess() {
|
|
||||||
setSuccess(false);
|
|
||||||
JDOMXPath xp_Success;
|
|
||||||
String text = null;
|
|
||||||
try {
|
|
||||||
xp_Success = new JDOMXPath("//message");
|
|
||||||
text = ((Element) xp_Success.selectSingleNode(this.license_doc)).getText();
|
|
||||||
setErrorMessage(text);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("There was an issue . . . " + text);
|
|
||||||
setSuccess(true);
|
|
||||||
}
|
|
||||||
return this.success;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSuccess(boolean success) {
|
|
||||||
this.success = success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getErrorMessage() {
|
|
||||||
return this.errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setErrorMessage(String errorMessage) {
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -13,7 +13,10 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import javax.xml.transform.Templates;
|
import javax.xml.transform.Templates;
|
||||||
import javax.xml.transform.TransformerConfigurationException;
|
import javax.xml.transform.TransformerConfigurationException;
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
@@ -82,9 +85,18 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
protected BundleService bundleService;
|
protected BundleService bundleService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected ItemService itemService;
|
protected ItemService itemService;
|
||||||
|
@Autowired
|
||||||
|
protected CCLicenseConnectorService ccLicenseConnectorService;
|
||||||
|
|
||||||
protected ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
protected ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
private String defaultLanguage;
|
||||||
|
private String jurisdiction;
|
||||||
|
private static final String JURISDICTION_KEY = "jurisdiction";
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String, Map<String, CCLicense>> ccLicenses;
|
||||||
|
|
||||||
protected CreativeCommonsServiceImpl() {
|
protected CreativeCommonsServiceImpl() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -101,10 +113,14 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
System.setProperty("http.proxyPort", proxyPort);
|
System.setProperty("http.proxyPort", proxyPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ccLicenses = new HashMap<>();
|
||||||
|
defaultLanguage = configurationService.getProperty("cc.license.locale", "en");
|
||||||
|
jurisdiction = configurationService.getProperty("cc.license.jurisdiction", "");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
templates = TransformerFactory.newInstance().newTemplates(
|
templates = TransformerFactory.newInstance().newTemplates(
|
||||||
new StreamSource(CreativeCommonsServiceImpl.class
|
new StreamSource(CreativeCommonsServiceImpl.class
|
||||||
.getResourceAsStream("CreativeCommons.xsl")));
|
.getResourceAsStream("CreativeCommons.xsl")));
|
||||||
} catch (TransformerConfigurationException e) {
|
} catch (TransformerConfigurationException e) {
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@@ -112,15 +128,10 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the CC bundle if it doesn't exist
|
// create the CC bundle if it doesn't exist
|
||||||
// If it does, remove it and create a new one.
|
// If it does, remove it and create a new one.
|
||||||
protected Bundle getCcBundle(Context context, Item item)
|
protected Bundle getCcBundle(Context context, Item item)
|
||||||
throws SQLException, AuthorizeException, IOException {
|
throws SQLException, AuthorizeException, IOException {
|
||||||
List<Bundle> bundles = itemService.getBundles(item, CC_BUNDLE_NAME);
|
List<Bundle> bundles = itemService.getBundles(item, CC_BUNDLE_NAME);
|
||||||
|
|
||||||
if ((bundles.size() > 0) && (bundles.get(0) != null)) {
|
if ((bundles.size() > 0) && (bundles.get(0) != null)) {
|
||||||
@@ -131,8 +142,8 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLicenseRDF(Context context, Item item, String licenseRdf)
|
public void setLicenseRDF(Context context, Item item, String licenseRdf)
|
||||||
throws SQLException, IOException,
|
throws SQLException, IOException,
|
||||||
AuthorizeException {
|
AuthorizeException {
|
||||||
Bundle bundle = getCcBundle(context, item);
|
Bundle bundle = getCcBundle(context, item);
|
||||||
// set the format
|
// set the format
|
||||||
BitstreamFormat bs_rdf_format = bitstreamFormatService.findByShortDescription(context, "RDF XML");
|
BitstreamFormat bs_rdf_format = bitstreamFormatService.findByShortDescription(context, "RDF XML");
|
||||||
@@ -144,7 +155,7 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
@Override
|
@Override
|
||||||
public void setLicense(Context context, Item item,
|
public void setLicense(Context context, Item item,
|
||||||
InputStream licenseStm, String mimeType)
|
InputStream licenseStm, String mimeType)
|
||||||
throws SQLException, IOException, AuthorizeException {
|
throws SQLException, IOException, AuthorizeException {
|
||||||
Bundle bundle = getCcBundle(context, item);
|
Bundle bundle = getCcBundle(context, item);
|
||||||
|
|
||||||
// set the format
|
// set the format
|
||||||
@@ -160,17 +171,26 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
Bitstream bs = bitstreamService.create(context, bundle, licenseStm);
|
Bitstream bs = bitstreamService.create(context, bundle, licenseStm);
|
||||||
bs.setSource(context, CC_BS_SOURCE);
|
bs.setSource(context, CC_BS_SOURCE);
|
||||||
bs.setName(context, (mimeType != null &&
|
bs.setName(context, (mimeType != null &&
|
||||||
(mimeType.equalsIgnoreCase("text/xml") ||
|
(mimeType.equalsIgnoreCase("text/xml") ||
|
||||||
mimeType.equalsIgnoreCase("text/rdf"))) ?
|
mimeType.equalsIgnoreCase("text/rdf"))) ?
|
||||||
BSN_LICENSE_RDF : BSN_LICENSE_TEXT);
|
BSN_LICENSE_RDF : BSN_LICENSE_TEXT);
|
||||||
bs.setFormat(context, bs_format);
|
bs.setFormat(context, bs_format);
|
||||||
bitstreamService.update(context, bs);
|
bitstreamService.update(context, bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the license file from the item
|
||||||
|
*
|
||||||
|
* @param context - The relevant DSpace Context
|
||||||
|
* @param item - The item from which the license file needs to be removed
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws AuthorizeException
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void removeLicense(Context context, Item item)
|
public void removeLicenseFile(Context context, Item item)
|
||||||
throws SQLException, IOException, AuthorizeException {
|
throws SQLException, IOException, AuthorizeException {
|
||||||
// remove CC license bundle if one exists
|
// remove CC license bundle if one exists
|
||||||
List<Bundle> bundles = itemService.getBundles(item, CC_BUNDLE_NAME);
|
List<Bundle> bundles = itemService.getBundles(item, CC_BUNDLE_NAME);
|
||||||
|
|
||||||
@@ -179,66 +199,74 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasLicense(Context context, Item item)
|
|
||||||
throws SQLException, IOException {
|
|
||||||
// try to find CC license bundle
|
|
||||||
List<Bundle> bundles = itemService.getBundles(item, CC_BUNDLE_NAME);
|
|
||||||
|
|
||||||
if (bundles.size() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify it has correct contents
|
|
||||||
try {
|
|
||||||
if ((getLicenseURL(context, item) == null)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (AuthorizeException ae) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getLicenseRDF(Context context, Item item) throws SQLException,
|
|
||||||
IOException, AuthorizeException {
|
|
||||||
return getStringFromBitstream(context, item, BSN_LICENSE_RDF);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bitstream getLicenseRdfBitstream(Item item) throws SQLException,
|
public Bitstream getLicenseRdfBitstream(Item item) throws SQLException,
|
||||||
IOException, AuthorizeException {
|
IOException, AuthorizeException {
|
||||||
return getBitstream(item, BSN_LICENSE_RDF);
|
return getBitstream(item, BSN_LICENSE_RDF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public Bitstream getLicenseTextBitstream(Item item) throws SQLException,
|
public Bitstream getLicenseTextBitstream(Item item) throws SQLException,
|
||||||
IOException, AuthorizeException {
|
IOException, AuthorizeException {
|
||||||
return getBitstream(item, BSN_LICENSE_TEXT);
|
return getBitstream(item, BSN_LICENSE_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLicenseURL(Context context, Item item) throws SQLException, IOException, AuthorizeException {
|
public String getLicenseURL(Context context, Item item) throws SQLException, IOException, AuthorizeException {
|
||||||
String licenseUri = getCCField("uri").ccItemValue(item);
|
String licenseUri = getCCField("uri");
|
||||||
if (StringUtils.isNotBlank(licenseUri)) {
|
if (StringUtils.isNotBlank(licenseUri)) {
|
||||||
return licenseUri;
|
return getLicenseURI(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSPUI backward compatibility see https://jira.duraspace.org/browse/DS-2604
|
// JSPUI backward compatibility see https://jira.duraspace.org/browse/DS-2604
|
||||||
return getStringFromBitstream(context, item, BSN_LICENSE_URL);
|
return getStringFromBitstream(context, item, BSN_LICENSE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stored license uri of the item
|
||||||
|
*
|
||||||
|
* @param item - The item for which to retrieve the stored license uri
|
||||||
|
* @return the stored license uri of the item
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getLicenseURI(Item item) {
|
||||||
|
String licenseUriField = getCCField("uri");
|
||||||
|
if (StringUtils.isNotBlank(licenseUriField)) {
|
||||||
|
String metadata = itemService.getMetadata(item, licenseUriField);
|
||||||
|
if (StringUtils.isNotBlank(metadata)) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stored license name of the item
|
||||||
|
*
|
||||||
|
* @param item - The item for which to retrieve the stored license name
|
||||||
|
* @return the stored license name of the item
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getLicenseName( Item item) {
|
||||||
|
String licenseNameField = getCCField("name");
|
||||||
|
if (StringUtils.isNotBlank(licenseNameField)) {
|
||||||
|
String metadata = itemService.getMetadata(item, licenseNameField);
|
||||||
|
if (StringUtils.isNotBlank(metadata)) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String fetchLicenseRDF(Document license) {
|
public String fetchLicenseRDF(Document license) {
|
||||||
StringWriter result = new StringWriter();
|
StringWriter result = new StringWriter();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
templates.newTransformer().transform(
|
templates.newTransformer().transform(
|
||||||
new JDOMSource(license),
|
new JDOMSource(license),
|
||||||
new StreamResult(result)
|
new StreamResult(result)
|
||||||
);
|
);
|
||||||
} catch (TransformerException e) {
|
} catch (TransformerException e) {
|
||||||
throw new IllegalStateException(e.getMessage(), e);
|
throw new IllegalStateException(e.getMessage(), e);
|
||||||
@@ -267,7 +295,7 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
*/
|
*/
|
||||||
protected void setBitstreamFromBytes(Context context, Item item, Bundle bundle,
|
protected void setBitstreamFromBytes(Context context, Item item, Bundle bundle,
|
||||||
String bitstream_name, BitstreamFormat format, byte[] bytes)
|
String bitstream_name, BitstreamFormat format, byte[] bytes)
|
||||||
throws SQLException, IOException, AuthorizeException {
|
throws SQLException, IOException, AuthorizeException {
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||||
Bitstream bs = bitstreamService.create(context, bundle, bais);
|
Bitstream bs = bitstreamService.create(context, bundle, bais);
|
||||||
|
|
||||||
@@ -297,7 +325,7 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
*/
|
*/
|
||||||
protected String getStringFromBitstream(Context context, Item item,
|
protected String getStringFromBitstream(Context context, Item item,
|
||||||
String bitstream_name) throws SQLException, IOException,
|
String bitstream_name) throws SQLException, IOException,
|
||||||
AuthorizeException {
|
AuthorizeException {
|
||||||
byte[] bytes = getBytesFromBitstream(context, item, bitstream_name);
|
byte[] bytes = getBytesFromBitstream(context, item, bitstream_name);
|
||||||
|
|
||||||
if (bytes == null) {
|
if (bytes == null) {
|
||||||
@@ -320,7 +348,7 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
* to perform a particular action.
|
* to perform a particular action.
|
||||||
*/
|
*/
|
||||||
protected Bitstream getBitstream(Item item, String bitstream_name)
|
protected Bitstream getBitstream(Item item, String bitstream_name)
|
||||||
throws SQLException, IOException, AuthorizeException {
|
throws SQLException, IOException, AuthorizeException {
|
||||||
Bundle cc_bundle = null;
|
Bundle cc_bundle = null;
|
||||||
|
|
||||||
// look for the CC bundle
|
// look for the CC bundle
|
||||||
@@ -342,7 +370,7 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] getBytesFromBitstream(Context context, Item item, String bitstream_name)
|
protected byte[] getBytesFromBitstream(Context context, Item item, String bitstream_name)
|
||||||
throws SQLException, IOException, AuthorizeException {
|
throws SQLException, IOException, AuthorizeException {
|
||||||
Bitstream bs = getBitstream(item, bitstream_name);
|
Bitstream bs = getBitstream(item, bitstream_name);
|
||||||
|
|
||||||
// no such bitstream
|
// no such bitstream
|
||||||
@@ -361,26 +389,322 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
|||||||
* Returns a metadata field handle for given field Id
|
* Returns a metadata field handle for given field Id
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public LicenseMetadataValue getCCField(String fieldId) {
|
public String getCCField(String fieldId) {
|
||||||
return new LicenseMetadataValue(configurationService.getProperty("cc.license." + fieldId));
|
return configurationService.getProperty("cc.license." + fieldId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove license information, delete also the bitstream
|
||||||
|
*
|
||||||
|
* @param context - DSpace Context
|
||||||
|
* @param item - the item
|
||||||
|
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
||||||
|
* to perform a particular action.
|
||||||
|
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void removeLicense(Context context, LicenseMetadataValue uriField,
|
public void removeLicense(Context context, Item item)
|
||||||
LicenseMetadataValue nameField, Item item)
|
throws AuthorizeException, IOException, SQLException {
|
||||||
throws AuthorizeException, IOException, SQLException {
|
|
||||||
|
String uriField = getCCField("uri");
|
||||||
|
String nameField = getCCField("name");
|
||||||
|
|
||||||
|
String licenseUri = itemService.getMetadata(item, uriField);
|
||||||
|
|
||||||
// only remove any previous licenses
|
// only remove any previous licenses
|
||||||
String licenseUri = uriField.ccItemValue(item);
|
|
||||||
if (licenseUri != null) {
|
if (licenseUri != null) {
|
||||||
uriField.removeItemValue(context, item, licenseUri);
|
removeLicenseField(context, item, uriField);
|
||||||
if (configurationService.getBooleanProperty("cc.submit.setname")) {
|
if (configurationService.getBooleanProperty("cc.submit.setname")) {
|
||||||
String licenseName = nameField.keyedItemValue(item, licenseUri);
|
removeLicenseField(context, item, nameField);
|
||||||
nameField.removeItemValue(context, item, licenseName);
|
|
||||||
}
|
}
|
||||||
if (configurationService.getBooleanProperty("cc.submit.addbitstream")) {
|
if (configurationService.getBooleanProperty("cc.submit.addbitstream")) {
|
||||||
removeLicense(context, item);
|
removeLicenseFile(context, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeLicenseField(Context context, Item item, String field) throws SQLException {
|
||||||
|
String[] params = splitField(field);
|
||||||
|
itemService.clearMetadata(context, item, params[0], params[1], params[2], params[3]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLicenseField(Context context, Item item, String field, String value) throws SQLException {
|
||||||
|
String[] params = splitField(field);
|
||||||
|
itemService.addMetadata(context, item, params[0], params[1], params[2], params[3], value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all CC Licenses using the default language found in the configuration
|
||||||
|
*
|
||||||
|
* @return A list of available CC Licenses
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<CCLicense> findAllCCLicenses() {
|
||||||
|
return findAllCCLicenses(defaultLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all CC Licenses for the provided language
|
||||||
|
*
|
||||||
|
* @param language - the language for which to find the CC Licenses
|
||||||
|
* @return A list of available CC Licenses for the provided language
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<CCLicense> findAllCCLicenses(String language) {
|
||||||
|
|
||||||
|
if (!ccLicenses.containsKey(language)) {
|
||||||
|
initLicenses(language);
|
||||||
|
}
|
||||||
|
return new LinkedList<>(ccLicenses.get(language).values());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the CC License corresponding to the provided ID using the default language found in the configuration
|
||||||
|
*
|
||||||
|
* @param id - the ID of the license to be found
|
||||||
|
* @return the corresponding license if found or null when not found
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CCLicense findOne(String id) {
|
||||||
|
return findOne(id, defaultLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the CC License corresponding to the provided ID and provided language
|
||||||
|
*
|
||||||
|
* @param id - the ID of the license to be found
|
||||||
|
* @param language - the language for which to find the CC License
|
||||||
|
* @return the corresponding license if found or null when not found
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CCLicense findOne(String id, String language) {
|
||||||
|
if (!ccLicenses.containsKey(language)) {
|
||||||
|
initLicenses(language);
|
||||||
|
}
|
||||||
|
Map<String, CCLicense> licenseMap = ccLicenses.get(language);
|
||||||
|
if (licenseMap.containsKey(id)) {
|
||||||
|
return licenseMap.get(id);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the licenses for a specific language and cache them in this service
|
||||||
|
*
|
||||||
|
* @param language - the language for which to find the CC Licenses
|
||||||
|
*/
|
||||||
|
private void initLicenses(final String language) {
|
||||||
|
Map<String, CCLicense> licenseMap = ccLicenseConnectorService.retrieveLicenses(language);
|
||||||
|
ccLicenses.put(language, licenseMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CC License URI for the provided license ID, based on the provided answers, using the default
|
||||||
|
* language found in the configuration
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the corresponding license URI
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String retrieveLicenseUri(String licenseId, Map<String, String> answerMap) {
|
||||||
|
return retrieveLicenseUri(licenseId, defaultLanguage, answerMap);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CC License URI for the provided license ID and language based on the provided answers
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to find the CC License URI
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the corresponding license URI
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String retrieveLicenseUri(String licenseId, String language, Map<String, String> answerMap) {
|
||||||
|
return ccLicenseConnectorService.retrieveRightsByQuestion(licenseId, language, answerMap);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify whether the answer map contains a valid response to all field questions and no answers that don't have a
|
||||||
|
* corresponding question in the license, using the default language found in the config to check the license
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param fullAnswerMap - the answers to the different field questions
|
||||||
|
* @return whether the information is valid
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean verifyLicenseInformation(String licenseId, Map<String, String> fullAnswerMap) {
|
||||||
|
return verifyLicenseInformation(licenseId, defaultLanguage, fullAnswerMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify whether the answer map contains a valid response to all field questions and no answers that don't have a
|
||||||
|
* corresponding question in the license, using the provided language to check the license
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to retrieve the full answerMap
|
||||||
|
* @param fullAnswerMap - the answers to the different field questions
|
||||||
|
* @return whether the information is valid
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean verifyLicenseInformation(String licenseId, String language, Map<String, String> fullAnswerMap) {
|
||||||
|
CCLicense ccLicense = findOne(licenseId, language);
|
||||||
|
|
||||||
|
List<CCLicenseField> ccLicenseFieldList = ccLicense.getCcLicenseFieldList();
|
||||||
|
|
||||||
|
for (String field : fullAnswerMap.keySet()) {
|
||||||
|
CCLicenseField ccLicenseField = findCCLicenseField(field, ccLicenseFieldList);
|
||||||
|
if (ccLicenseField == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!containsAnswerEnum(fullAnswerMap.get(field), ccLicenseField)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the full answer map containing empty values when an answer for a field was not provided in the
|
||||||
|
* answerMap, using the default language found in the configuration
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the answerMap supplemented with all other license fields with a blank answer
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> retrieveFullAnswerMap(String licenseId, Map<String, String> answerMap) {
|
||||||
|
return retrieveFullAnswerMap(licenseId, defaultLanguage, answerMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the full answer map for a provided language, containing empty values when an answer for a field was not
|
||||||
|
* provided in the answerMap.
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to retrieve the full answerMap
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the answerMap supplemented with all other license fields with a blank answer for the provided language
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> retrieveFullAnswerMap(String licenseId, String language, Map<String, String> answerMap) {
|
||||||
|
CCLicense ccLicense = findOne(licenseId, language);
|
||||||
|
if (ccLicense == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Map<String, String> fullParamMap = new HashMap<>(answerMap);
|
||||||
|
List<CCLicenseField> ccLicenseFieldList = ccLicense.getCcLicenseFieldList();
|
||||||
|
for (CCLicenseField ccLicenseField : ccLicenseFieldList) {
|
||||||
|
if (!fullParamMap.containsKey(ccLicenseField.getId())) {
|
||||||
|
fullParamMap.put(ccLicenseField.getId(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateJurisdiction(fullParamMap);
|
||||||
|
|
||||||
|
return fullParamMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateJurisdiction(final Map<String, String> fullParamMap) {
|
||||||
|
if (fullParamMap.containsKey(JURISDICTION_KEY)) {
|
||||||
|
fullParamMap.put(JURISDICTION_KEY, jurisdiction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsAnswerEnum(final String enumAnswer, final CCLicenseField ccLicenseField) {
|
||||||
|
List<CCLicenseFieldEnum> fieldEnums = ccLicenseField.getFieldEnum();
|
||||||
|
for (CCLicenseFieldEnum fieldEnum : fieldEnums) {
|
||||||
|
if (StringUtils.equals(fieldEnum.getId(), enumAnswer)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CCLicenseField findCCLicenseField(final String field, final List<CCLicenseField> ccLicenseFieldList) {
|
||||||
|
for (CCLicenseField ccLicenseField : ccLicenseFieldList) {
|
||||||
|
if (StringUtils.equals(ccLicenseField.getId(), field)) {
|
||||||
|
return ccLicenseField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the license of the item with a new one based on the provided license URI
|
||||||
|
*
|
||||||
|
* @param context - The relevant DSpace context
|
||||||
|
* @param licenseUri - The license URI to be used in the update
|
||||||
|
* @param item - The item for which to update the license
|
||||||
|
* @return true when the update was successful, false when not
|
||||||
|
* @throws AuthorizeException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean updateLicense(final Context context, final String licenseUri, final Item item)
|
||||||
|
throws AuthorizeException, SQLException {
|
||||||
|
try {
|
||||||
|
Document doc = ccLicenseConnectorService.retrieveLicenseRDFDoc(licenseUri);
|
||||||
|
if (doc == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String licenseName = ccLicenseConnectorService.retrieveLicenseName(doc);
|
||||||
|
if (StringUtils.isBlank(licenseName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeLicense(context, item);
|
||||||
|
addLicense(context, item, licenseUri, licenseName, doc);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error while updating the license of item: " + item.getID(), e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new license to the item
|
||||||
|
*
|
||||||
|
* @param context - The relevant Dspace context
|
||||||
|
* @param item - The item to which the license will be added
|
||||||
|
* @param licenseUri - The license URI to add
|
||||||
|
* @param licenseName - The license name to add
|
||||||
|
* @param doc - The license to document to add
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws AuthorizeException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addLicense(Context context, Item item, String licenseUri, String licenseName, Document doc)
|
||||||
|
throws SQLException, IOException, AuthorizeException {
|
||||||
|
String uriField = getCCField("uri");
|
||||||
|
String nameField = getCCField("name");
|
||||||
|
|
||||||
|
addLicenseField(context, item, uriField, licenseUri);
|
||||||
|
if (configurationService.getBooleanProperty("cc.submit.addbitstream")) {
|
||||||
|
setLicenseRDF(context, item, fetchLicenseRDF(doc));
|
||||||
|
}
|
||||||
|
if (configurationService.getBooleanProperty("cc.submit.setname")) {
|
||||||
|
addLicenseField(context, item, nameField, licenseName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] splitField(String fieldName) {
|
||||||
|
String[] params = new String[4];
|
||||||
|
String[] fParams = fieldName.split("\\.");
|
||||||
|
for (int i = 0; i < fParams.length; i++) {
|
||||||
|
params[i] = fParams[i];
|
||||||
|
}
|
||||||
|
params[3] = Item.ANY;
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,129 +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.license;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.dspace.authorize.AuthorizeException;
|
|
||||||
import org.dspace.content.Item;
|
|
||||||
import org.dspace.content.MetadataValue;
|
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
|
||||||
import org.dspace.content.service.ItemService;
|
|
||||||
import org.dspace.core.Context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class for using CC-related Metadata fields
|
|
||||||
*
|
|
||||||
* @author kevinvandevelde at atmire.com
|
|
||||||
*/
|
|
||||||
public class LicenseMetadataValue {
|
|
||||||
|
|
||||||
protected final ItemService itemService;
|
|
||||||
// Shibboleth for Creative Commons license data - i.e. characters that reliably indicate CC in a URI
|
|
||||||
protected static final String ccShib = "creativecommons";
|
|
||||||
|
|
||||||
private String[] params = new String[4];
|
|
||||||
|
|
||||||
public LicenseMetadataValue(String fieldName) {
|
|
||||||
if (fieldName != null && fieldName.length() > 0) {
|
|
||||||
String[] fParams = fieldName.split("\\.");
|
|
||||||
for (int i = 0; i < fParams.length; i++) {
|
|
||||||
params[i] = fParams[i];
|
|
||||||
}
|
|
||||||
params[3] = Item.ANY;
|
|
||||||
}
|
|
||||||
itemService = ContentServiceFactory.getInstance().getItemService();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns first value that matches Creative Commons 'shibboleth',
|
|
||||||
* or null if no matching values.
|
|
||||||
* NB: this method will succeed only for metadata fields holding CC URIs
|
|
||||||
*
|
|
||||||
* @param item - the item to read
|
|
||||||
* @return value - the first CC-matched value, or null if no such value
|
|
||||||
*/
|
|
||||||
public String ccItemValue(Item item) {
|
|
||||||
List<MetadataValue> dcvalues = itemService.getMetadata(item, params[0], params[1], params[2], params[3]);
|
|
||||||
for (MetadataValue dcvalue : dcvalues) {
|
|
||||||
if ((dcvalue.getValue()).indexOf(ccShib) != -1) {
|
|
||||||
// return first value that matches the shib
|
|
||||||
return dcvalue.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value that matches the value mapped to the passed key if any.
|
|
||||||
* NB: this only delivers a license name (if present in field) given a license URI
|
|
||||||
*
|
|
||||||
* @param item - the item to read
|
|
||||||
* @param key - the key for desired value
|
|
||||||
* @return value - the value associated with key or null if no such value
|
|
||||||
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
|
||||||
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
|
||||||
* to perform a particular action.
|
|
||||||
*/
|
|
||||||
public String keyedItemValue(Item item, String key)
|
|
||||||
throws AuthorizeException, IOException, SQLException {
|
|
||||||
CCLookup ccLookup = new CCLookup();
|
|
||||||
ccLookup.issue(key);
|
|
||||||
String matchValue = ccLookup.getLicenseName();
|
|
||||||
List<MetadataValue> dcvalues = itemService.getMetadata(item, params[0], params[1], params[2], params[3]);
|
|
||||||
for (MetadataValue dcvalue : dcvalues) {
|
|
||||||
if (dcvalue.getValue().equals(matchValue)) {
|
|
||||||
return dcvalue.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the passed value from the set of values for the field in passed item.
|
|
||||||
*
|
|
||||||
* @param context The relevant DSpace Context.
|
|
||||||
* @param item - the item to update
|
|
||||||
* @param value - the value to remove
|
|
||||||
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
|
||||||
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
|
||||||
* to perform a particular action.
|
|
||||||
*/
|
|
||||||
public void removeItemValue(Context context, Item item, String value)
|
|
||||||
throws AuthorizeException, IOException, SQLException {
|
|
||||||
if (value != null) {
|
|
||||||
List<MetadataValue> dcvalues = itemService.getMetadata(item, params[0], params[1], params[2], params[3]);
|
|
||||||
ArrayList<String> arrayList = new ArrayList<String>();
|
|
||||||
for (MetadataValue dcvalue : dcvalues) {
|
|
||||||
if (!dcvalue.getValue().equals(value)) {
|
|
||||||
arrayList.add(dcvalue.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
itemService.clearMetadata(context, item, params[0], params[1], params[2], params[3]);
|
|
||||||
itemService.addMetadata(context, item, params[0], params[1], params[2], params[3], arrayList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds passed value to the set of values for the field in passed item.
|
|
||||||
*
|
|
||||||
* @param context The relevant DSpace Context.
|
|
||||||
* @param item - the item to update
|
|
||||||
* @param value - the value to add in this field
|
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
|
||||||
*/
|
|
||||||
public void addItemValue(Context context, Item item, String value) throws SQLException {
|
|
||||||
itemService.addMetadata(context, item, params[0], params[1], params[2], params[3], value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -10,12 +10,14 @@ package org.dspace.license.service;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.license.LicenseMetadataValue;
|
import org.dspace.license.CCLicense;
|
||||||
import org.jdom.Document;
|
import org.jdom.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,13 +31,6 @@ public interface CreativeCommonsService {
|
|||||||
|
|
||||||
public static final String CC_BUNDLE_NAME = "CC-LICENSE";
|
public static final String CC_BUNDLE_NAME = "CC-LICENSE";
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple accessor for enabling of CC
|
|
||||||
*
|
|
||||||
* @return is CC enabled?
|
|
||||||
*/
|
|
||||||
public boolean isEnabled();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* setLicenseRDF
|
* setLicenseRDF
|
||||||
*
|
*
|
||||||
@@ -50,7 +45,7 @@ public interface CreativeCommonsService {
|
|||||||
* to perform a particular action.
|
* to perform a particular action.
|
||||||
*/
|
*/
|
||||||
public void setLicenseRDF(Context context, Item item, String licenseRdf)
|
public void setLicenseRDF(Context context, Item item, String licenseRdf)
|
||||||
throws SQLException, IOException, AuthorizeException;
|
throws SQLException, IOException, AuthorizeException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,19 +67,40 @@ public interface CreativeCommonsService {
|
|||||||
*/
|
*/
|
||||||
public void setLicense(Context context, Item item,
|
public void setLicense(Context context, Item item,
|
||||||
InputStream licenseStm, String mimeType)
|
InputStream licenseStm, String mimeType)
|
||||||
throws SQLException, IOException, AuthorizeException;
|
throws SQLException, IOException, AuthorizeException;
|
||||||
|
|
||||||
public void removeLicense(Context context, Item item)
|
/**
|
||||||
throws SQLException, IOException, AuthorizeException;
|
* Removes the license file from the item
|
||||||
|
*
|
||||||
|
* @param context - The relevant DSpace Context
|
||||||
|
* @param item - The item from which the license file needs to be removed
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws AuthorizeException
|
||||||
|
*/
|
||||||
|
public void removeLicenseFile(Context context, Item item)
|
||||||
|
throws SQLException, IOException, AuthorizeException;
|
||||||
|
|
||||||
public boolean hasLicense(Context context, Item item)
|
|
||||||
throws SQLException, IOException;
|
|
||||||
|
|
||||||
public String getLicenseURL(Context context, Item item)
|
public String getLicenseURL(Context context, Item item)
|
||||||
throws SQLException, IOException, AuthorizeException;
|
throws SQLException, IOException, AuthorizeException;
|
||||||
|
|
||||||
public String getLicenseRDF(Context context, Item item)
|
|
||||||
throws SQLException, IOException, AuthorizeException;
|
/**
|
||||||
|
* Returns the stored license uri of the item
|
||||||
|
*
|
||||||
|
* @param item - The item for which to retrieve the stored license uri
|
||||||
|
* @return the stored license uri of the item
|
||||||
|
*/
|
||||||
|
public String getLicenseURI(Item item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stored license name of the item
|
||||||
|
*
|
||||||
|
* @param item - The item for which to retrieve the stored license name
|
||||||
|
* @return the stored license name of the item
|
||||||
|
*/
|
||||||
|
public String getLicenseName(Item item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Creative Commons license RDF, returning Bitstream object.
|
* Get Creative Commons license RDF, returning Bitstream object.
|
||||||
@@ -97,7 +113,7 @@ public interface CreativeCommonsService {
|
|||||||
* to perform a particular action.
|
* to perform a particular action.
|
||||||
*/
|
*/
|
||||||
public Bitstream getLicenseRdfBitstream(Item item)
|
public Bitstream getLicenseRdfBitstream(Item item)
|
||||||
throws SQLException, IOException, AuthorizeException;
|
throws SQLException, IOException, AuthorizeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Creative Commons license Text, returning Bitstream object.
|
* Get Creative Commons license Text, returning Bitstream object.
|
||||||
@@ -112,7 +128,7 @@ public interface CreativeCommonsService {
|
|||||||
* is no longer stored (see https://jira.duraspace.org/browse/DS-2604)
|
* is no longer stored (see https://jira.duraspace.org/browse/DS-2604)
|
||||||
*/
|
*/
|
||||||
public Bitstream getLicenseTextBitstream(Item item)
|
public Bitstream getLicenseTextBitstream(Item item)
|
||||||
throws SQLException, IOException, AuthorizeException;
|
throws SQLException, IOException, AuthorizeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a few license-specific properties. We expect these to be cached at
|
* Get a few license-specific properties. We expect these to be cached at
|
||||||
@@ -121,7 +137,7 @@ public interface CreativeCommonsService {
|
|||||||
* @param fieldId name of the property.
|
* @param fieldId name of the property.
|
||||||
* @return its value.
|
* @return its value.
|
||||||
*/
|
*/
|
||||||
public LicenseMetadataValue getCCField(String fieldId);
|
public String getCCField(String fieldId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply same transformation on the document to retrieve only the most
|
* Apply same transformation on the document to retrieve only the most
|
||||||
@@ -138,15 +154,134 @@ public interface CreativeCommonsService {
|
|||||||
* Remove license information, delete also the bitstream
|
* Remove license information, delete also the bitstream
|
||||||
*
|
*
|
||||||
* @param context - DSpace Context
|
* @param context - DSpace Context
|
||||||
* @param uriField - the metadata field for license uri
|
|
||||||
* @param nameField - the metadata field for license name
|
|
||||||
* @param item - the item
|
* @param item - the item
|
||||||
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
||||||
* to perform a particular action.
|
* to perform a particular action.
|
||||||
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public void removeLicense(Context context, LicenseMetadataValue uriField,
|
public void removeLicense(Context context, Item item)
|
||||||
LicenseMetadataValue nameField, Item item)
|
throws AuthorizeException, IOException, SQLException;
|
||||||
throws AuthorizeException, IOException, SQLException;
|
|
||||||
|
/**
|
||||||
|
* Find all CC Licenses using the default language found in the configuration
|
||||||
|
*
|
||||||
|
* @return A list of available CC Licenses
|
||||||
|
*/
|
||||||
|
public List<CCLicense> findAllCCLicenses();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all CC Licenses for the provided language
|
||||||
|
*
|
||||||
|
* @param language - the language for which to find the CC Licenses
|
||||||
|
* @return A list of available CC Licenses for the provided language
|
||||||
|
*/
|
||||||
|
public List<CCLicense> findAllCCLicenses(String language);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the CC License corresponding to the provided ID using the default language found in the configuration
|
||||||
|
*
|
||||||
|
* @param id - the ID of the license to be found
|
||||||
|
* @return the corresponding license if found or null when not found
|
||||||
|
*/
|
||||||
|
public CCLicense findOne(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the CC License corresponding to the provided ID and provided language
|
||||||
|
*
|
||||||
|
* @param id - the ID of the license to be found
|
||||||
|
* @param language - the language for which to find the CC License
|
||||||
|
* @return the corresponding license if found or null when not found
|
||||||
|
*/
|
||||||
|
public CCLicense findOne(String id, String language);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CC License URI for the provided license ID, based on the provided answers, using the default
|
||||||
|
* language found in the configuration
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the corresponding license URI
|
||||||
|
*/
|
||||||
|
public String retrieveLicenseUri(String licenseId, Map<String, String> answerMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CC License URI for the provided license ID and language based on the provided answers
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to find the CC License URI
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the corresponding license URI
|
||||||
|
*/
|
||||||
|
public String retrieveLicenseUri(String licenseId, String language, Map<String, String> answerMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the full answer map containing empty values when an answer for a field was not provided in the
|
||||||
|
* answerMap, using the default language found in the configuration
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the answerMap supplemented with all other license fields with a blank answer
|
||||||
|
*/
|
||||||
|
public Map<String, String> retrieveFullAnswerMap(String licenseId, Map<String, String> answerMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the full answer map for a provided language, containing empty values when an answer for a field was not
|
||||||
|
* provided in the answerMap.
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to retrieve the full answerMap
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the answerMap supplemented with all other license fields with a blank answer for the provided language
|
||||||
|
*/
|
||||||
|
public Map<String, String> retrieveFullAnswerMap(String licenseId, String language, Map<String, String> answerMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify whether the answer map contains a valid response to all field questions and no answers that don't have a
|
||||||
|
* corresponding question in the license, using the default language found in the config to check the license
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param fullAnswerMap - the answers to the different field questions
|
||||||
|
* @return whether the information is valid
|
||||||
|
*/
|
||||||
|
public boolean verifyLicenseInformation(String licenseId, Map<String, String> fullAnswerMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify whether the answer map contains a valid response to all field questions and no answers that don't have a
|
||||||
|
* corresponding question in the license, using the provided language to check the license
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to retrieve the full answerMap
|
||||||
|
* @param fullAnswerMap - the answers to the different field questions
|
||||||
|
* @return whether the information is valid
|
||||||
|
*/
|
||||||
|
public boolean verifyLicenseInformation(String licenseId, String language, Map<String, String> fullAnswerMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the license of the item with a new one based on the provided license URI
|
||||||
|
*
|
||||||
|
* @param context - The relevant DSpace context
|
||||||
|
* @param licenseUri - The license URI to be used in the update
|
||||||
|
* @param item - The item for which to update the license
|
||||||
|
* @return true when the update was successful, false when not
|
||||||
|
* @throws AuthorizeException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public boolean updateLicense(final Context context, String licenseUri, final Item item)
|
||||||
|
throws AuthorizeException, SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new license to the item
|
||||||
|
*
|
||||||
|
* @param context - The relevant Dspace context
|
||||||
|
* @param item - The item to which the license will be added
|
||||||
|
* @param licenseUri - The license URI to add
|
||||||
|
* @param licenseName - The license name to add
|
||||||
|
* @param doc - The license to document to add
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws AuthorizeException
|
||||||
|
*/
|
||||||
|
public void addLicense(Context context, Item item, String licenseUri, String licenseName, Document doc)
|
||||||
|
throws SQLException, IOException, AuthorizeException;
|
||||||
}
|
}
|
||||||
|
@@ -7,70 +7,72 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.scripts;
|
package org.dspace.scripts;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.io.InputStream;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.DefaultParser;
|
import org.apache.commons.cli.DefaultParser;
|
||||||
|
import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.dspace.authorize.service.AuthorizeService;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
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.
|
* This is the class that should be extended for each Script. This class will contain the logic needed to run and it'll
|
||||||
* it provides the basic variables to be hold by the script as well as the means to initialize, parse and run the script
|
* fetch the information that it needs from the {@link ScriptConfiguration} provided through the diamond operators.
|
||||||
* Every DSpaceRunnable that is implemented in this way should be defined in the scripts.xml config file as a bean
|
* This will be the dspaceRunnableClass for the {@link ScriptConfiguration} beans. Specifically created for each
|
||||||
|
* script
|
||||||
|
* @param <T>
|
||||||
*/
|
*/
|
||||||
public abstract class DSpaceRunnable implements Runnable {
|
public abstract class DSpaceRunnable<T extends ScriptConfiguration> 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
|
* The CommandLine object for the script that'll hold the information
|
||||||
*/
|
*/
|
||||||
protected CommandLine commandLine;
|
protected CommandLine commandLine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The possible options for this script
|
* This EPerson identifier variable is the uuid of the eperson that's running the script
|
||||||
*/
|
*/
|
||||||
protected Options options;
|
private UUID epersonIdentifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The handler that deals with this script. This handler can currently either be a RestDSpaceRunnableHandler or
|
* 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
|
* a CommandlineDSpaceRunnableHandler depending from where the script is called
|
||||||
*/
|
*/
|
||||||
protected DSpaceRunnableHandler handler;
|
protected DSpaceRunnableHandler handler;
|
||||||
|
|
||||||
@Autowired
|
/**
|
||||||
private AuthorizeService authorizeService;
|
* This method will return the Configuration that the implementing DSpaceRunnable uses
|
||||||
|
* @return The {@link ScriptConfiguration} that this implementing DspaceRunnable uses
|
||||||
|
*/
|
||||||
|
public abstract T getScriptConfiguration();
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
private void setHandler(DSpaceRunnableHandler dSpaceRunnableHandler) {
|
||||||
|
this.handler = dSpaceRunnableHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Required
|
/**
|
||||||
public void setName(String name) {
|
* This method sets the appropriate DSpaceRunnableHandler depending on where it was ran from and it parses
|
||||||
this.name = name;
|
* 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
|
||||||
public String getDescription() {
|
* @param currentUser
|
||||||
return description;
|
* @throws ParseException If something goes wrong
|
||||||
}
|
*/
|
||||||
|
public void initialize(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||||
@Required
|
EPerson currentUser) throws ParseException {
|
||||||
public void setDescription(String description) {
|
if (currentUser != null) {
|
||||||
this.description = description;
|
this.setEpersonIdentifier(currentUser.getID());
|
||||||
}
|
}
|
||||||
|
this.setHandler(dSpaceRunnableHandler);
|
||||||
public Options getOptions() {
|
this.parse(args);
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,18 +82,16 @@ public abstract class DSpaceRunnable implements Runnable {
|
|||||||
* @throws ParseException If something goes wrong
|
* @throws ParseException If something goes wrong
|
||||||
*/
|
*/
|
||||||
private void parse(String[] args) throws ParseException {
|
private void parse(String[] args) throws ParseException {
|
||||||
commandLine = new DefaultParser().parse(getOptions(), args);
|
commandLine = new DefaultParser().parse(getScriptConfiguration().getOptions(), args);
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will call upon the {@link DSpaceRunnableHandler#printHelp(Options, String)} method with the script's
|
* This method has to be included in every script and handles the setup of the script by parsing the CommandLine
|
||||||
* options and name
|
* and setting the variables
|
||||||
|
* @throws ParseException If something goes wrong
|
||||||
*/
|
*/
|
||||||
public void printHelp() {
|
public abstract void setup() throws ParseException;
|
||||||
handler.printHelp(options, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the run() method from the Runnable interface that we implement. This method will handle the running
|
* This is the run() method from the Runnable interface that we implement. This method will handle the running
|
||||||
@@ -108,22 +108,6 @@ public abstract class DSpaceRunnable implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
* 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
|
* contain all the logic needed
|
||||||
@@ -132,25 +116,46 @@ public abstract class DSpaceRunnable implements Runnable {
|
|||||||
public abstract void internalRun() throws Exception;
|
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
|
* This method will call upon the {@link DSpaceRunnableHandler#printHelp(Options, String)} method with the script's
|
||||||
* and setting the variables
|
* options and name
|
||||||
* @throws ParseException If something goes wrong
|
|
||||||
*/
|
*/
|
||||||
public abstract void setup() throws ParseException;
|
public void printHelp() {
|
||||||
|
handler.printHelp(getScriptConfiguration().getOptions(), getScriptConfiguration().getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will return if the script is allowed to execute in the given context. This is by default set
|
* This method will traverse all the options and it'll grab options defined as an InputStream type to then save
|
||||||
* to the currentUser in the context being an admin, however this can be overwritten by each script individually
|
* the filename specified by that option in a list of Strings that'll be returned in the end
|
||||||
* if different rules apply
|
* @return The list of Strings representing filenames from the options given to the script
|
||||||
* @param context The relevant DSpace context
|
|
||||||
* @return A boolean indicating whether the script is allowed to execute or not
|
|
||||||
*/
|
*/
|
||||||
public boolean isAllowedToExecute(Context context) {
|
public List<String> getFileNamesFromInputStreamOptions() {
|
||||||
try {
|
List<String> fileNames = new LinkedList<>();
|
||||||
return authorizeService.isAdmin(context);
|
|
||||||
} catch (SQLException e) {
|
for (Option option : getScriptConfiguration().getOptions().getOptions()) {
|
||||||
handler.logError("Error occured when trying to verify permissions for script: " + name);
|
if (option.getType() == InputStream.class &&
|
||||||
|
StringUtils.isNotBlank(commandLine.getOptionValue(option.getOpt()))) {
|
||||||
|
fileNames.add(commandLine.getOptionValue(option.getOpt()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return fileNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the epersonIdentifier
|
||||||
|
* This EPerson identifier variable is the uuid of the eperson that's running the script
|
||||||
|
* @return the epersonIdentifier value of this DSpaceRunnable
|
||||||
|
*/
|
||||||
|
public UUID getEpersonIdentifier() {
|
||||||
|
return epersonIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the epersonIdentifier
|
||||||
|
* This EPerson identifier variable is the uuid of the eperson that's running the script
|
||||||
|
* @param epersonIdentifier The epersonIdentifier to be set on this DSpaceRunnable
|
||||||
|
*/
|
||||||
|
public void setEpersonIdentifier(UUID epersonIdentifier) {
|
||||||
|
this.epersonIdentifier = epersonIdentifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.scripts;
|
package org.dspace.scripts;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
@@ -80,6 +81,8 @@ public class Process implements ReloadableEntity<Integer> {
|
|||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
private Date creationTime;
|
private Date creationTime;
|
||||||
|
|
||||||
|
public static final String BITSTREAM_TYPE_METADATAFIELD = "dspace.process.filetype";
|
||||||
|
|
||||||
protected Process() {
|
protected Process() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +177,9 @@ public class Process implements ReloadableEntity<Integer> {
|
|||||||
* @return The Bitstreams that are used or created by the process
|
* @return The Bitstreams that are used or created by the process
|
||||||
*/
|
*/
|
||||||
public List<Bitstream> getBitstreams() {
|
public List<Bitstream> getBitstreams() {
|
||||||
|
if (bitstreams == null) {
|
||||||
|
bitstreams = new LinkedList<>();
|
||||||
|
}
|
||||||
return bitstreams;
|
return bitstreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,18 +7,33 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.scripts;
|
package org.dspace.scripts;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.ListUtils;
|
||||||
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.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.MetadataField;
|
||||||
|
import org.dspace.content.MetadataValue;
|
||||||
import org.dspace.content.ProcessStatus;
|
import org.dspace.content.ProcessStatus;
|
||||||
import org.dspace.content.dao.ProcessDAO;
|
import org.dspace.content.dao.ProcessDAO;
|
||||||
|
import org.dspace.content.service.BitstreamFormatService;
|
||||||
|
import org.dspace.content.service.BitstreamService;
|
||||||
|
import org.dspace.content.service.MetadataFieldService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.LogManager;
|
import org.dspace.core.LogManager;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
@@ -35,6 +50,18 @@ public class ProcessServiceImpl implements ProcessService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ProcessDAO processDAO;
|
private ProcessDAO processDAO;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BitstreamService bitstreamService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BitstreamFormatService bitstreamFormatService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MetadataFieldService metadataFieldService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Process create(Context context, EPerson ePerson, String scriptName,
|
public Process create(Context context, EPerson ePerson, String scriptName,
|
||||||
List<DSpaceCommandLineParameter> parameters) throws SQLException {
|
List<DSpaceCommandLineParameter> parameters) throws SQLException {
|
||||||
@@ -113,11 +140,35 @@ public class ProcessServiceImpl implements ProcessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(Context context, Process process) throws SQLException {
|
public void appendFile(Context context, Process process, InputStream is, String type, String fileName)
|
||||||
|
throws IOException, SQLException, AuthorizeException {
|
||||||
|
Bitstream bitstream = bitstreamService.create(context, is);
|
||||||
|
if (getBitstream(context, process, type) != null) {
|
||||||
|
throw new IllegalArgumentException("Cannot create another file of type: " + type + " for this process" +
|
||||||
|
" with id: " + process.getID());
|
||||||
|
}
|
||||||
|
bitstream.setName(context, fileName);
|
||||||
|
bitstreamService.setFormat(context, bitstream, bitstreamFormatService.guessFormat(context, bitstream));
|
||||||
|
MetadataField dspaceProcessFileTypeField = metadataFieldService
|
||||||
|
.findByString(context, Process.BITSTREAM_TYPE_METADATAFIELD, '.');
|
||||||
|
bitstreamService.addMetadata(context, bitstream, dspaceProcessFileTypeField, null, type);
|
||||||
|
authorizeService.addPolicy(context, bitstream, Constants.READ, context.getCurrentUser());
|
||||||
|
authorizeService.addPolicy(context, bitstream, Constants.WRITE, context.getCurrentUser());
|
||||||
|
authorizeService.addPolicy(context, bitstream, Constants.DELETE, context.getCurrentUser());
|
||||||
|
bitstreamService.update(context, bitstream);
|
||||||
|
process.addBitstream(bitstream);
|
||||||
|
update(context, process);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(Context context, Process process) throws SQLException, IOException, AuthorizeException {
|
||||||
|
|
||||||
|
for (Bitstream bitstream : ListUtils.emptyIfNull(process.getBitstreams())) {
|
||||||
|
bitstreamService.delete(context, bitstream);
|
||||||
|
}
|
||||||
processDAO.delete(context, process);
|
processDAO.delete(context, process);
|
||||||
log.info(LogManager.getHeader(context, "process_delete", "Process with ID " + process.getID()
|
log.info(LogManager.getHeader(context, "process_delete", "Process with ID " + process.getID()
|
||||||
+ " and name " + process.getName() + " has been deleted"));
|
+ " and name " + process.getName() + " has been deleted"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -141,8 +192,57 @@ public class ProcessServiceImpl implements ProcessService {
|
|||||||
return parameterList;
|
return parameterList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bitstream getBitstreamByName(Context context, Process process, String bitstreamName) {
|
||||||
|
for (Bitstream bitstream : getBitstreams(context, process)) {
|
||||||
|
if (StringUtils.equals(bitstream.getName(), bitstreamName)) {
|
||||||
|
return bitstream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bitstream getBitstream(Context context, Process process, String type) {
|
||||||
|
List<Bitstream> allBitstreams = process.getBitstreams();
|
||||||
|
|
||||||
|
if (type == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
if (allBitstreams != null) {
|
||||||
|
for (Bitstream bitstream : allBitstreams) {
|
||||||
|
if (StringUtils.equals(bitstreamService.getMetadata(bitstream,
|
||||||
|
Process.BITSTREAM_TYPE_METADATAFIELD), type)) {
|
||||||
|
return bitstream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Bitstream> getBitstreams(Context context, Process process) {
|
||||||
|
return process.getBitstreams();
|
||||||
|
}
|
||||||
|
|
||||||
public int countTotal(Context context) throws SQLException {
|
public int countTotal(Context context) throws SQLException {
|
||||||
return processDAO.countRows(context);
|
return processDAO.countRows(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFileTypesForProcessBitstreams(Context context, Process process) {
|
||||||
|
List<Bitstream> list = getBitstreams(context, process);
|
||||||
|
Set<String> fileTypesSet = new HashSet<>();
|
||||||
|
for (Bitstream bitstream : list) {
|
||||||
|
List<MetadataValue> metadata = bitstreamService.getMetadata(bitstream,
|
||||||
|
Process.BITSTREAM_TYPE_METADATAFIELD, Item.ANY);
|
||||||
|
if (metadata != null && !metadata.isEmpty()) {
|
||||||
|
fileTypesSet.add(metadata.get(0).getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>(fileTypesSet);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,33 +7,46 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.scripts;
|
package org.dspace.scripts;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.kernel.ServiceManager;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
import org.dspace.scripts.service.ScriptService;
|
import org.dspace.scripts.service.ScriptService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The implementation for the {@link ScriptService}
|
* The implementation for the {@link ScriptService}
|
||||||
*/
|
*/
|
||||||
public class ScriptServiceImpl implements ScriptService {
|
public class ScriptServiceImpl implements ScriptService {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ScriptServiceImpl.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private List<DSpaceRunnable> dSpaceRunnables;
|
private ServiceManager serviceManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DSpaceRunnable getScriptForName(String name) {
|
public ScriptConfiguration getScriptConfiguration(String name) {
|
||||||
return dSpaceRunnables.stream()
|
return serviceManager.getServiceByName(name, ScriptConfiguration.class);
|
||||||
.filter(dSpaceRunnable -> StringUtils.equalsIgnoreCase(dSpaceRunnable.getName(), name))
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DSpaceRunnable> getDSpaceRunnables(Context context) {
|
public List<ScriptConfiguration> getScriptConfigurations(Context context) {
|
||||||
return dSpaceRunnables.stream().filter(
|
return serviceManager.getServicesByType(ScriptConfiguration.class).stream().filter(
|
||||||
dSpaceRunnable -> dSpaceRunnable.isAllowedToExecute(context)).collect(Collectors.toList());
|
scriptConfiguration -> scriptConfiguration.isAllowedToExecute(context)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DSpaceRunnable createDSpaceRunnableForScriptConfiguration(ScriptConfiguration scriptToExecute)
|
||||||
|
throws IllegalAccessException, InstantiationException {
|
||||||
|
try {
|
||||||
|
return (DSpaceRunnable) scriptToExecute.getDspaceRunnableClass().getDeclaredConstructor().newInstance();
|
||||||
|
} catch (InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* 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.configuration;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.springframework.beans.factory.BeanNameAware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents an Abstract class that a ScriptConfiguration can inherit to further implement this
|
||||||
|
* and represent a script's configuration
|
||||||
|
*/
|
||||||
|
public abstract class ScriptConfiguration<T extends DSpaceRunnable> implements BeanNameAware {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The possible options for this script
|
||||||
|
*/
|
||||||
|
protected Options options;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the description
|
||||||
|
* @return the description value of this ScriptConfiguration
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the description
|
||||||
|
* @param description The description to be set on this ScriptConfiguration
|
||||||
|
*/
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the name
|
||||||
|
* @return the name value of this ScriptConfiguration
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the name
|
||||||
|
* @param name The name to be set on this ScriptConfiguration
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the dspaceRunnableClass
|
||||||
|
* @return the dspaceRunnableClass value of this ScriptConfiguration
|
||||||
|
*/
|
||||||
|
public abstract Class<T> getDspaceRunnableClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the dspaceRunnableClass
|
||||||
|
* @param dspaceRunnableClass The dspaceRunnableClass to be set on this IndexDiscoveryScriptConfiguration
|
||||||
|
*/
|
||||||
|
public abstract void setDspaceRunnableClass(Class<T> dspaceRunnableClass);
|
||||||
|
/**
|
||||||
|
* 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 abstract boolean isAllowedToExecute(Context context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The getter for the options of the Script
|
||||||
|
* @return the options value of this ScriptConfiguration
|
||||||
|
*/
|
||||||
|
public abstract Options getOptions();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBeanName(String beanName) {
|
||||||
|
this.name = beanName;
|
||||||
|
}
|
||||||
|
}
|
@@ -7,9 +7,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.scripts.handler;
|
package org.dspace.scripts.handler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an interface meant to be implemented by any DSpaceRunnableHandler to specify specific execution methods
|
* This is an interface meant to be implemented by any DSpaceRunnableHandler to specify specific execution methods
|
||||||
@@ -78,4 +83,28 @@ public interface DSpaceRunnableHandler {
|
|||||||
* @param name The name of the script
|
* @param name The name of the script
|
||||||
*/
|
*/
|
||||||
public void printHelp(Options options, String name);
|
public void printHelp(Options options, String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will grab the InputStream for the file defined by the given file name. The exact implementation will
|
||||||
|
* differ based on whether it's a REST call or CommandLine call. The REST Call will look for Bitstreams in the
|
||||||
|
* Database whereas the CommandLine call will look on the filesystem
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param fileName The filename for the file that holds the InputStream
|
||||||
|
* @return The InputStream for the file defined by the given file name
|
||||||
|
* @throws IOException If something goes wrong
|
||||||
|
* @throws AuthorizeException If something goes wrong
|
||||||
|
*/
|
||||||
|
public Optional<InputStream> getFileStream(Context context, String fileName) throws IOException, AuthorizeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will write the InputStream to either a file on the filesystem or a bitstream in the database
|
||||||
|
* depending on whether it's coming from a CommandLine call or REST call respectively
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param fileName The filename
|
||||||
|
* @param inputStream The inputstream to be written
|
||||||
|
* @param type The type of the file
|
||||||
|
* @throws IOException If something goes wrong
|
||||||
|
*/
|
||||||
|
public void writeFilestream(Context context, String fileName, InputStream inputStream, String type)
|
||||||
|
throws IOException, SQLException, AuthorizeException;
|
||||||
}
|
}
|
||||||
|
@@ -7,9 +7,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.scripts.handler.impl;
|
package org.dspace.scripts.handler.impl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apache.commons.cli.HelpFormatter;
|
import org.apache.commons.cli.HelpFormatter;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.core.Context;
|
||||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,4 +91,20 @@ public class CommandLineDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
|||||||
formatter.printHelp(name, options);
|
formatter.printHelp(name, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<InputStream> getFileStream(Context context, String fileName) throws IOException {
|
||||||
|
File file = new File(fileName);
|
||||||
|
if (!(file.exists() && file.isFile())) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return Optional.of(FileUtils.openInputStream(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeFilestream(Context context, String fileName, InputStream inputStream, String type)
|
||||||
|
throws IOException {
|
||||||
|
File file = new File(fileName);
|
||||||
|
FileUtils.copyInputStreamToFile(inputStream, file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,9 +7,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.scripts.service;
|
package org.dspace.scripts.service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||||
@@ -104,13 +108,28 @@ public interface ProcessService {
|
|||||||
*/
|
*/
|
||||||
public void complete(Context context, Process process) throws SQLException;
|
public void complete(Context context, Process process) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method will create a bitstream from the given inputstream with the given type as metadata and given name
|
||||||
|
* as name and attach it to the given process
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param process The process for which the bitstream will be made
|
||||||
|
* @param is The inputstream for the bitstream
|
||||||
|
* @param type The type of the bitstream
|
||||||
|
* @param fileName The name of the bitstream
|
||||||
|
* @throws IOException If something goes wrong
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
* @throws AuthorizeException If something goes wrong
|
||||||
|
*/
|
||||||
|
public void appendFile(Context context, Process process, InputStream is, String type, String fileName)
|
||||||
|
throws IOException, SQLException, AuthorizeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will delete the given Process object from the database
|
* This method will delete the given Process object from the database
|
||||||
* @param context The relevant DSpace context
|
* @param context The relevant DSpace context
|
||||||
* @param process The Process object to be deleted
|
* @param process The Process object to be deleted
|
||||||
* @throws SQLException If something goes wrong
|
* @throws SQLException If something goes wrong
|
||||||
*/
|
*/
|
||||||
public void delete(Context context, Process process) throws SQLException;
|
public void delete(Context context, Process process) throws SQLException, IOException, AuthorizeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will be used to update the given Process object in the database
|
* This method will be used to update the given Process object in the database
|
||||||
@@ -128,6 +147,32 @@ public interface ProcessService {
|
|||||||
*/
|
*/
|
||||||
public List<DSpaceCommandLineParameter> getParameters(Process process);
|
public List<DSpaceCommandLineParameter> getParameters(Process process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will return the Bitstream that matches the given name for the given Process
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param process The process that should hold the requested Bitstream
|
||||||
|
* @param bitstreamName The name of the requested Bitstream
|
||||||
|
* @return The Bitstream from the given Process that matches the given bitstream name
|
||||||
|
*/
|
||||||
|
public Bitstream getBitstreamByName(Context context, Process process, String bitstreamName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will return the Bitstream for a given process with a given type
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param process The process that holds the Bitstreams to be searched in
|
||||||
|
* @param type The type that the Bitstream must have
|
||||||
|
* @return The Bitstream of the given type for the given Process
|
||||||
|
*/
|
||||||
|
public Bitstream getBitstream(Context context, Process process, String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will return all the Bitstreams for a given process
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param process The process that holds the Bitstreams to be searched in
|
||||||
|
* @return The list of Bitstreams
|
||||||
|
*/
|
||||||
|
public List<Bitstream> getBitstreams(Context context, Process process);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total amount of Process objects in the dataase
|
* Returns the total amount of Process objects in the dataase
|
||||||
* @param context The relevant DSpace context
|
* @param context The relevant DSpace context
|
||||||
@@ -136,4 +181,12 @@ public interface ProcessService {
|
|||||||
*/
|
*/
|
||||||
int countTotal(Context context) throws SQLException;
|
int countTotal(Context context) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will return a list of Strings where each String represents the type of a Bitstream in the Process given
|
||||||
|
* @param context The DSpace context
|
||||||
|
* @param process The Process object that we'll use to find the bitstreams
|
||||||
|
* @return A list of Strings where each String represents a fileType that is in the Process
|
||||||
|
*/
|
||||||
|
public List<String> getFileTypesForProcessBitstreams(Context context, Process process);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.scripts.DSpaceRunnable;
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This service will deal with logic to handle DSpaceRunnable objects
|
* This service will deal with logic to handle DSpaceRunnable objects
|
||||||
@@ -18,16 +19,29 @@ import org.dspace.scripts.DSpaceRunnable;
|
|||||||
public interface ScriptService {
|
public interface ScriptService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will return the DSpaceRunnable that has the name that's equal to the name given in the parameters
|
* This method will return the ScriptConfiguration that has the name that's equal to the name given in the
|
||||||
|
* parameters
|
||||||
* @param name The name that the script has to match
|
* @param name The name that the script has to match
|
||||||
* @return The matching DSpaceRunnable script
|
* @return The matching ScriptConfiguration
|
||||||
*/
|
*/
|
||||||
DSpaceRunnable getScriptForName(String name);
|
ScriptConfiguration getScriptConfiguration(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will return a list of DSpaceRunnable objects for which the given Context is authorized to use them
|
* This method will return a list of ScriptConfiguration objects for which the given Context is authorized
|
||||||
* @param context The relevant DSpace context
|
* @param context The relevant DSpace context
|
||||||
* @return The list of accessible DSpaceRunnable scripts for this context
|
* @return The list of accessible ScriptConfiguration scripts for this context
|
||||||
*/
|
*/
|
||||||
List<DSpaceRunnable> getDSpaceRunnables(Context context);
|
List<ScriptConfiguration> getScriptConfigurations(Context context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will create a new instance of the DSpaceRunnable that's linked with this Scriptconfiguration
|
||||||
|
* It'll grab the DSpaceRunnable class from the ScriptConfiguration's variables and create a new instance of it
|
||||||
|
* to return
|
||||||
|
* @param scriptToExecute The relevant ScriptConfiguration
|
||||||
|
* @return The new instance of the DSpaceRunnable class
|
||||||
|
* @throws IllegalAccessException If something goes wrong
|
||||||
|
* @throws InstantiationException If something goes wrong
|
||||||
|
*/
|
||||||
|
DSpaceRunnable createDSpaceRunnableForScriptConfiguration(ScriptConfiguration scriptToExecute)
|
||||||
|
throws IllegalAccessException, InstantiationException;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,2 @@
|
|||||||
|
id,collection,dc.contributor.author
|
||||||
|
+,"123456789/2","Donald, SmithImported"
|
|
@@ -82,9 +82,9 @@
|
|||||||
<!--Step will be to select a Creative Commons License -->
|
<!--Step will be to select a Creative Commons License -->
|
||||||
<!-- Uncomment this step to allow the user to select a Creative Commons
|
<!-- Uncomment this step to allow the user to select a Creative Commons
|
||||||
license -->
|
license -->
|
||||||
<!-- <step id="creative-commons"> <heading>submit.progressbar.CClicense</heading>
|
<step id="cclicense"> <heading>submit.progressbar.CClicense</heading>
|
||||||
<processing-class>org.dspace.submit.step.CCLicenseStep</processing-class>
|
<processing-class>org.dspace.app.rest.submit.step.CCLicenseStep</processing-class>
|
||||||
<type>cclicense</type> </step> -->
|
<type>cclicense</type> </step>
|
||||||
|
|
||||||
<!--Step will be to Check for potential duplicate -->
|
<!--Step will be to Check for potential duplicate -->
|
||||||
<!-- <step id="detect-duplicate"> <heading>submit.progressbar.detect.duplicate</heading>
|
<!-- <step id="detect-duplicate"> <heading>submit.progressbar.detect.duplicate</heading>
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
|
|
||||||
<!--Step will be to Sign off on the License -->
|
<!--Step will be to Sign off on the License -->
|
||||||
<step id="license"/>
|
<step id="license"/>
|
||||||
<!-- <step id="creative-commons"/> -->
|
<step id="cclicense"/>
|
||||||
<!-- <step id="verify"/> -->
|
<!-- <step id="verify"/> -->
|
||||||
</submission-process>
|
</submission-process>
|
||||||
|
|
||||||
|
@@ -4,13 +4,23 @@
|
|||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||||
|
|
||||||
<bean id="indexClient" class="org.dspace.discovery.IndexClient" scope="prototype">
|
<bean id="index-discovery" class="org.dspace.discovery.IndexDiscoveryScriptConfiguration">
|
||||||
<property name="name" value="index-discovery"/>
|
|
||||||
<property name="description" value="Update Discovery Solr Search Index"/>
|
<property name="description" value="Update Discovery Solr Search Index"/>
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.discovery.IndexClient"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="MockScript" class="org.dspace.scripts.impl.MockDSpaceRunnableScript" scope="prototype">
|
<bean id="metadata-import" class="org.dspace.app.bulkedit.MetadataImportCliScriptConfiguration">
|
||||||
<property name="name" value="mock-script" />
|
<property name="description" value="Import metadata after batch editing" />
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.app.bulkedit.MetadataImportCLI"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="metadata-export" class="org.dspace.app.bulkedit.MetadataExportScriptConfiguration">
|
||||||
|
<property name="description" value="Export metadata for batch editing"/>
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.app.bulkedit.MetadataExport"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="mock-script" class="org.dspace.scripts.MockDSpaceRunnableScriptConfiguration" scope="prototype">
|
||||||
<property name="description" value="Mocking a script for testing purposes" />
|
<property name="description" value="Mocking a script for testing purposes" />
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.scripts.impl.MockDSpaceRunnableScript"/>
|
||||||
</bean>
|
</bean>
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -18,6 +18,7 @@ import java.io.OutputStreamWriter;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.AbstractUnitTest;
|
import org.dspace.AbstractUnitTest;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -67,7 +68,7 @@ public class DSpaceCSVTest extends AbstractUnitTest {
|
|||||||
out = null;
|
out = null;
|
||||||
|
|
||||||
// Test the CSV parsing was OK
|
// Test the CSV parsing was OK
|
||||||
DSpaceCSV dcsv = new DSpaceCSV(new File(filename), context);
|
DSpaceCSV dcsv = new DSpaceCSV(FileUtils.openInputStream(new File(filename)), context);
|
||||||
String[] lines = dcsv.getCSVLinesAsStringArray();
|
String[] lines = dcsv.getCSVLinesAsStringArray();
|
||||||
assertThat("testDSpaceCSV Good CSV", lines.length, equalTo(8));
|
assertThat("testDSpaceCSV Good CSV", lines.length, equalTo(8));
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ public class DSpaceCSVTest extends AbstractUnitTest {
|
|||||||
|
|
||||||
// Test the CSV parsing was OK
|
// Test the CSV parsing was OK
|
||||||
try {
|
try {
|
||||||
dcsv = new DSpaceCSV(new File(filename), context);
|
dcsv = new DSpaceCSV(FileUtils.openInputStream(new File(filename)), context);
|
||||||
lines = dcsv.getCSVLinesAsStringArray();
|
lines = dcsv.getCSVLinesAsStringArray();
|
||||||
|
|
||||||
fail("An exception should have been thrown due to bad CSV");
|
fail("An exception should have been thrown due to bad CSV");
|
||||||
@@ -124,7 +125,7 @@ public class DSpaceCSVTest extends AbstractUnitTest {
|
|||||||
|
|
||||||
// Test the CSV parsing was OK
|
// Test the CSV parsing was OK
|
||||||
try {
|
try {
|
||||||
dcsv = new DSpaceCSV(new File(filename), context);
|
dcsv = new DSpaceCSV(FileUtils.openInputStream(new File(filename)), context);
|
||||||
lines = dcsv.getCSVLinesAsStringArray();
|
lines = dcsv.getCSVLinesAsStringArray();
|
||||||
|
|
||||||
fail("An exception should have been thrown due to bad CSV");
|
fail("An exception should have been thrown due to bad CSV");
|
||||||
|
@@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkedit;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.dspace.AbstractIntegrationTest;
|
||||||
|
import org.dspace.app.launcher.ScriptLauncher;
|
||||||
|
import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.WorkspaceItem;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.CollectionService;
|
||||||
|
import org.dspace.content.service.CommunityService;
|
||||||
|
import org.dspace.content.service.InstallItemService;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.content.service.WorkspaceItemService;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class MetadataExportTest extends AbstractIntegrationTest {
|
||||||
|
|
||||||
|
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
private CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||||
|
private CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
|
||||||
|
private WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
|
||||||
|
private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService();
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void metadataExportToCsvTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = communityService.create(null, context);
|
||||||
|
Collection collection = collectionService.create(context, community);
|
||||||
|
WorkspaceItem wi = workspaceItemService.create(context, collection, true);
|
||||||
|
Item item = wi.getItem();
|
||||||
|
itemService.addMetadata(context, item, "dc", "contributor", "author", null, "Donald, Smith");
|
||||||
|
item = installItemService.installItem(context, wi);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
String fileLocation = configurationService.getProperty("dspace.dir") + testProps.get("test.exportcsv")
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
String[] args = new String[] {"metadata-export", "-i", String.valueOf(item.getHandle()), "-f", fileLocation};
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
File file = new File(fileLocation);
|
||||||
|
String fileContent = IOUtils.toString(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||||
|
assertTrue(fileContent.contains("Donald, Smith"));
|
||||||
|
assertTrue(fileContent.contains(String.valueOf(item.getID())));
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
itemService.delete(context, itemService.find(context, item.getID()));
|
||||||
|
collectionService.delete(context, collectionService.find(context, collection.getID()));
|
||||||
|
communityService.delete(context, communityService.find(context, community.getID()));
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkedit;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.AbstractIntegrationTest;
|
||||||
|
import org.dspace.app.launcher.ScriptLauncher;
|
||||||
|
import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.CollectionService;
|
||||||
|
import org.dspace.content.service.CommunityService;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class MetadataImportTest extends AbstractIntegrationTest {
|
||||||
|
|
||||||
|
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
private CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||||
|
private CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void metadataImportTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = communityService.create(null, context);
|
||||||
|
Collection collection = collectionService.create(context, community);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String fileLocation = new File(testProps.get("test.importcsv").toString()).getAbsolutePath();
|
||||||
|
String[] args = new String[] {"metadata-import", "-f", fileLocation, "-e", eperson.getEmail(), "-s"};
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
Item importedItem = itemService.findAll(context).next();
|
||||||
|
assertTrue(
|
||||||
|
StringUtils.equals(
|
||||||
|
itemService.getMetadata(importedItem, "dc", "contributor", "author", Item.ANY).get(0).getValue(),
|
||||||
|
"Donald, SmithImported"));
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
itemService.delete(context, itemService.find(context, importedItem.getID()));
|
||||||
|
collectionService.delete(context, collectionService.find(context, collection.getID()));
|
||||||
|
communityService.delete(context, communityService.find(context, community.getID()));
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* 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.scripts.handler.impl;
|
||||||
|
|
||||||
|
import org.dspace.scripts.handler.impl.CommandLineDSpaceRunnableHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class will be used as a DSpaceRunnableHandler for the Tests so that we can stop the handler
|
||||||
|
* from calling System.exit() when a script would throw an exception
|
||||||
|
*/
|
||||||
|
public class TestDSpaceRunnableHandler extends CommandLineDSpaceRunnableHandler {
|
||||||
|
|
||||||
|
private Exception exception = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We're overriding this method so that we can stop the script from doing the System.exit() if
|
||||||
|
* an exception within the script is thrown
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleException(String message, Exception e) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the exception
|
||||||
|
* @return the exception value of this TestDSpaceRunnableHandler
|
||||||
|
*/
|
||||||
|
public Exception getException() {
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* 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.license;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jdom.Document;
|
||||||
|
import org.jdom.JDOMException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock implementation for the Creative commons license connector service.
|
||||||
|
* This class will return a structure of CC Licenses similar to the CC License API but without having to contact it
|
||||||
|
*/
|
||||||
|
public class MockCCLicenseConnectorServiceImpl extends CCLicenseConnectorServiceImpl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves mock CC Licenses for the provided language
|
||||||
|
* @param language - the language
|
||||||
|
* @return a map of mocked licenses with the id and the license
|
||||||
|
*/
|
||||||
|
public Map<String, CCLicense> retrieveLicenses(String language) {
|
||||||
|
Map<String, CCLicense> ccLicenses = new HashMap<>();
|
||||||
|
CCLicense mockLicense1 = createMockLicense(1, new int[]{3, 2, 3});
|
||||||
|
CCLicense mockLicense2 = createMockLicense(2, new int[]{2});
|
||||||
|
CCLicense mockLicense3 = createMockLicense(3, new int[]{});
|
||||||
|
|
||||||
|
ccLicenses.put(mockLicense1.getLicenseId(), mockLicense1);
|
||||||
|
ccLicenses.put(mockLicense2.getLicenseId(), mockLicense2);
|
||||||
|
ccLicenses.put(mockLicense3.getLicenseId(), mockLicense3);
|
||||||
|
|
||||||
|
return ccLicenses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CCLicense createMockLicense(int count, int[] amountOfFieldsAndEnums) {
|
||||||
|
String licenseId = "license" + count;
|
||||||
|
String licenseName = "License " + count + " - Name";
|
||||||
|
List<CCLicenseField> mockLicenseFields = createMockLicenseFields(count, amountOfFieldsAndEnums);
|
||||||
|
return new CCLicense(licenseId, licenseName, mockLicenseFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CCLicenseField> createMockLicenseFields(int count, int[] amountOfFieldsAndEnums) {
|
||||||
|
List<CCLicenseField> ccLicenseFields = new LinkedList<>();
|
||||||
|
for (int index = 0; index < amountOfFieldsAndEnums.length; index++) {
|
||||||
|
String licenseFieldId = "license" + count + "-field" + index;
|
||||||
|
String licenseFieldLabel = "License " + count + " - Field " + index + " - Label";
|
||||||
|
String licenseFieldDescription = "License " + count + " - Field " + index + " - Description";
|
||||||
|
List<CCLicenseFieldEnum> mockLicenseFields = createMockLicenseFields(count,
|
||||||
|
index,
|
||||||
|
amountOfFieldsAndEnums[index]);
|
||||||
|
ccLicenseFields.add(new CCLicenseField(licenseFieldId,
|
||||||
|
licenseFieldLabel,
|
||||||
|
licenseFieldDescription,
|
||||||
|
mockLicenseFields));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ccLicenseFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CCLicenseFieldEnum> createMockLicenseFields(int count, int index, int amountOfEnums) {
|
||||||
|
List<CCLicenseFieldEnum> ccLicenseFieldEnumList = new LinkedList<>();
|
||||||
|
for (int i = 0; i < amountOfEnums; i++) {
|
||||||
|
String enumId = "license" + count + "-field" + index + "-enum" + i;
|
||||||
|
String enumLabel = "License " + count + " - Field " + index + " - Enum " + i + " - Label";
|
||||||
|
String enumDescription = "License " + count + " - Field " + index + " - Enum " + i + " - " +
|
||||||
|
"Description";
|
||||||
|
ccLicenseFieldEnumList.add(new CCLicenseFieldEnum(enumId, enumLabel, enumDescription));
|
||||||
|
}
|
||||||
|
return ccLicenseFieldEnumList;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a mock CC License URI
|
||||||
|
*
|
||||||
|
* @param licenseId - the ID of the license
|
||||||
|
* @param language - the language for which to retrieve the full answerMap
|
||||||
|
* @param answerMap - the answers to the different field questions
|
||||||
|
* @return the CC License URI
|
||||||
|
*/
|
||||||
|
public String retrieveRightsByQuestion(final String licenseId,
|
||||||
|
final String language,
|
||||||
|
final Map<String, String> answerMap) {
|
||||||
|
|
||||||
|
return "mock-license-uri";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a mock license RDF document.
|
||||||
|
* When the uri contains "invalid", null will be returned to simulate that no document was found for the provided
|
||||||
|
* URI
|
||||||
|
*
|
||||||
|
* @param licenseURI - The license URI for which to retrieve the license RDF document
|
||||||
|
* @return a mock license RDF document or null when the URI contains invalid
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public Document retrieveLicenseRDFDoc(String licenseURI) throws IOException {
|
||||||
|
if (!StringUtils.contains(licenseURI, "invalid")) {
|
||||||
|
InputStream cclicense = null;
|
||||||
|
try {
|
||||||
|
cclicense = getClass().getResourceAsStream("cc-license-rdf.xml");
|
||||||
|
|
||||||
|
Document doc = parser.build(cclicense);
|
||||||
|
return doc;
|
||||||
|
} catch (JDOMException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
if (cclicense != null) {
|
||||||
|
cclicense.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* 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.io.InputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
import org.dspace.scripts.impl.MockDSpaceRunnableScript;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
public class MockDSpaceRunnableScriptConfiguration<T extends MockDSpaceRunnableScript> extends ScriptConfiguration<T> {
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
private Class<T> dspaceRunnableClass;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getDspaceRunnableClass() {
|
||||||
|
return dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the dspaceRunnableClass
|
||||||
|
* @param dspaceRunnableClass The dspaceRunnableClass to be set on this MetadataExportScriptConfiguration
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
|
||||||
|
this.dspaceRunnableClass = dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowedToExecute(Context context) {
|
||||||
|
try {
|
||||||
|
return authorizeService.isAdmin(context);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("SQLException occurred when checking if the current user is an admin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Options getOptions() {
|
||||||
|
if (options == null) {
|
||||||
|
Options options = new Options();
|
||||||
|
|
||||||
|
options.addOption("r", "remove", true, "description r");
|
||||||
|
options.getOption("r").setType(String.class);
|
||||||
|
options.addOption("i", "index", false, "description i");
|
||||||
|
options.getOption("i").setType(boolean.class);
|
||||||
|
options.getOption("i").setRequired(true);
|
||||||
|
options.addOption("f", "file", true, "source file");
|
||||||
|
options.getOption("f").setType(InputStream.class);
|
||||||
|
options.getOption("f").setRequired(false);
|
||||||
|
super.options = options;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
}
|
@@ -7,19 +7,20 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.scripts.impl;
|
package org.dspace.scripts.impl;
|
||||||
|
|
||||||
import org.apache.commons.cli.Options;
|
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.dspace.scripts.DSpaceRunnable;
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.scripts.MockDSpaceRunnableScriptConfiguration;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
|
||||||
public class MockDSpaceRunnableScript extends DSpaceRunnable {
|
public class MockDSpaceRunnableScript extends DSpaceRunnable<MockDSpaceRunnableScriptConfiguration> {
|
||||||
|
@Override
|
||||||
private MockDSpaceRunnableScript() {
|
public void internalRun() throws Exception {
|
||||||
Options options = constructOptions();
|
|
||||||
this.options = options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void internalRun() throws Exception {
|
public MockDSpaceRunnableScriptConfiguration getScriptConfiguration() {
|
||||||
|
return new DSpace().getServiceManager()
|
||||||
|
.getServiceByName("mock-script", MockDSpaceRunnableScriptConfiguration.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -28,15 +29,4 @@ public class MockDSpaceRunnableScript extends DSpaceRunnable {
|
|||||||
throw new ParseException("-i is a mandatory parameter");
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -11,3 +11,5 @@ test.folder = ./target/testing/
|
|||||||
|
|
||||||
# Path of the test bitstream (to use in BitstreamTest and elsewhere)
|
# Path of the test bitstream (to use in BitstreamTest and elsewhere)
|
||||||
test.bitstream = ./target/testing/dspace/assetstore/ConstitutionofIreland.pdf
|
test.bitstream = ./target/testing/dspace/assetstore/ConstitutionofIreland.pdf
|
||||||
|
test.exportcsv = ./target/testing/dspace/assetstore/test.csv
|
||||||
|
test.importcsv = ./target/testing/dspace/assetstore/testImport.csv
|
||||||
|
@@ -274,16 +274,16 @@ public class CollectionsResource extends Resource {
|
|||||||
headers, request, context);
|
headers, request, context);
|
||||||
|
|
||||||
items = new ArrayList<Item>();
|
items = new ArrayList<Item>();
|
||||||
Iterator<org.dspace.content.Item> dspaceItems = itemService.findByCollection(context, dspaceCollection);
|
Iterator<org.dspace.content.Item> dspaceItems = itemService.findByCollection(context, dspaceCollection,
|
||||||
for (int i = 0; (dspaceItems.hasNext()) && (i < (limit + offset)); i++) {
|
limit, offset);
|
||||||
|
|
||||||
|
while (dspaceItems.hasNext()) {
|
||||||
org.dspace.content.Item dspaceItem = dspaceItems.next();
|
org.dspace.content.Item dspaceItem = dspaceItems.next();
|
||||||
|
|
||||||
if (i >= offset) {
|
if (itemService.isItemListedForUser(context, dspaceItem)) {
|
||||||
if (itemService.isItemListedForUser(context, dspaceItem)) {
|
items.add(new Item(dspaceItem, servletContext, expand, context));
|
||||||
items.add(new Item(dspaceItem, servletContext, expand, context));
|
writeStats(dspaceItem, UsageEvent.Action.VIEW, user_ip, user_agent, xforwardedfor,
|
||||||
writeStats(dspaceItem, UsageEvent.Action.VIEW, user_ip, user_agent, xforwardedfor,
|
headers, request, context);
|
||||||
headers, request, context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -342,7 +342,15 @@ public class RestResourceController implements InitializingBean {
|
|||||||
return findRelEntryInternal(request, response, apiCategory, model, id, rel, relid, page, assembler);
|
return findRelEntryInternal(request, response, apiCategory, model, id, rel, relid, page, assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT +
|
||||||
|
"/{rel}/{relid}")
|
||||||
|
public RepresentationModel findRel(HttpServletRequest request, HttpServletResponse response,
|
||||||
|
@PathVariable String apiCategory,
|
||||||
|
@PathVariable String model, @PathVariable Integer id, @PathVariable String rel,
|
||||||
|
@PathVariable String relid,
|
||||||
|
Pageable page, PagedResourcesAssembler assembler) throws Throwable {
|
||||||
|
return findRelEntryInternal(request, response, apiCategory, model, id.toString(), rel, relid, page, assembler);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Execute a POST request;
|
* Execute a POST request;
|
||||||
*
|
*
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.rest;
|
package org.dspace.app.rest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
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.converter.ConverterService;
|
||||||
@@ -27,7 +29,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
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.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller adds additional subresource methods to allow connecting scripts with processes
|
* This controller adds additional subresource methods to allow connecting scripts with processes
|
||||||
@@ -56,13 +60,14 @@ public class ScriptProcessesController {
|
|||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
@RequestMapping(method = RequestMethod.POST)
|
||||||
@PreAuthorize("hasAuthority('ADMIN')")
|
@PreAuthorize("hasAuthority('ADMIN')")
|
||||||
public ResponseEntity<RepresentationModel<?>> startProcess(@PathVariable(name = "name") String scriptName)
|
public ResponseEntity<RepresentationModel<?>> startProcess(@PathVariable(name = "name") String scriptName,
|
||||||
|
@RequestParam(name = "file") List<MultipartFile> files)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
if (log.isTraceEnabled()) {
|
if (log.isTraceEnabled()) {
|
||||||
log.trace("Starting Process for Script with name: " + scriptName);
|
log.trace("Starting Process for Script with name: " + scriptName);
|
||||||
}
|
}
|
||||||
Context context = ContextUtil.obtainContext(requestService.getCurrentRequest().getServletRequest());
|
Context context = ContextUtil.obtainContext(requestService.getCurrentRequest().getServletRequest());
|
||||||
ProcessRest processRest = scriptRestRepository.startProcess(context, scriptName);
|
ProcessRest processRest = scriptRestRepository.startProcess(context, scriptName, files);
|
||||||
ProcessResource processResource = converter.toResource(processRest);
|
ProcessResource processResource = converter.toResource(processRest);
|
||||||
context.complete();
|
context.complete();
|
||||||
return ControllerUtils.toResponseEntity(HttpStatus.ACCEPTED, new HttpHeaders(), processResource);
|
return ControllerUtils.toResponseEntity(HttpStatus.ACCEPTED, new HttpHeaders(), processResource);
|
||||||
|
@@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.app.rest.converter.ConverterService;
|
||||||
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
|
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseUrlRest;
|
||||||
|
import org.dspace.app.rest.model.wrapper.SubmissionCCLicenseUrl;
|
||||||
|
import org.dspace.app.rest.repository.DSpaceRestRepository;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.license.service.CreativeCommonsService;
|
||||||
|
import org.dspace.services.RequestService;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||||
|
import org.springframework.hateoas.Link;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Repository is responsible for handling the CC License URIs.
|
||||||
|
* It only supports a search method
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Component(SubmissionCCLicenseUrlRest.CATEGORY + "." + SubmissionCCLicenseUrlRest.NAME)
|
||||||
|
public class SubmissionCCLicenseUrlRepository extends DSpaceRestRepository<SubmissionCCLicenseUrlRest, String>
|
||||||
|
implements InitializingBean {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected Utils utils;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected CreativeCommonsService creativeCommonsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected ConverterService converter;
|
||||||
|
|
||||||
|
protected RequestService requestService = new DSpace().getRequestService();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DiscoverableEndpointsService discoverableEndpointsService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the CC License URI based on the license ID and answers in the field questions, provided as parameters
|
||||||
|
* to this request
|
||||||
|
*
|
||||||
|
* @return the CC License URI as a SubmissionCCLicenseUrlRest
|
||||||
|
*/
|
||||||
|
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||||
|
@SearchRestMethod(name = "rightsByQuestions")
|
||||||
|
public SubmissionCCLicenseUrlRest findByRightsByQuestions() {
|
||||||
|
ServletRequest servletRequest = requestService.getCurrentRequest()
|
||||||
|
.getServletRequest();
|
||||||
|
Map<String, String[]> requestParameterMap = servletRequest
|
||||||
|
.getParameterMap();
|
||||||
|
Map<String, String> parameterMap = new HashMap<>();
|
||||||
|
String licenseId = servletRequest.getParameter("license");
|
||||||
|
if (StringUtils.isBlank(licenseId)) {
|
||||||
|
throw new DSpaceBadRequestException(
|
||||||
|
"A \"license\" parameter needs to be provided.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through parameters to find answer parameters, adding them to the parameterMap. Zero or more answers
|
||||||
|
// may exist, as some CC licenses do not require answers
|
||||||
|
for (String parameter : requestParameterMap.keySet()) {
|
||||||
|
if (StringUtils.startsWith(parameter, "answer_")) {
|
||||||
|
String field = StringUtils.substringAfter(parameter, "answer_");
|
||||||
|
String answer = "";
|
||||||
|
if (requestParameterMap.get(parameter).length > 0) {
|
||||||
|
answer = requestParameterMap.get(parameter)[0];
|
||||||
|
}
|
||||||
|
parameterMap.put(field, answer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> fullParamMap = creativeCommonsService.retrieveFullAnswerMap(licenseId, parameterMap);
|
||||||
|
if (fullParamMap == null) {
|
||||||
|
throw new ResourceNotFoundException("No CC License could be matched on the provided ID: " + licenseId);
|
||||||
|
}
|
||||||
|
boolean licenseContainsCorrectInfo = creativeCommonsService.verifyLicenseInformation(licenseId, fullParamMap);
|
||||||
|
if (!licenseContainsCorrectInfo) {
|
||||||
|
throw new DSpaceBadRequestException(
|
||||||
|
"The provided answers do not match the required fields for the provided license.");
|
||||||
|
}
|
||||||
|
|
||||||
|
String licenseUri = creativeCommonsService.retrieveLicenseUri(licenseId, fullParamMap);
|
||||||
|
|
||||||
|
SubmissionCCLicenseUrl submissionCCLicenseUrl = new SubmissionCCLicenseUrl(licenseUri, licenseUri);
|
||||||
|
if (StringUtils.isBlank(licenseUri)) {
|
||||||
|
throw new ResourceNotFoundException("No CC License URI could be found for ID: " + licenseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return converter.toRest(submissionCCLicenseUrl, utils.obtainProjection());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The findOne method is not supported in this repository
|
||||||
|
*/
|
||||||
|
@PreAuthorize("permitAll()")
|
||||||
|
public SubmissionCCLicenseUrlRest findOne(final Context context, final String s) {
|
||||||
|
throw new RepositoryMethodNotImplementedException(SubmissionCCLicenseUrlRest.NAME, "findOne");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The findAll method is not supported in this repository
|
||||||
|
*/
|
||||||
|
public Page<SubmissionCCLicenseUrlRest> findAll(final Context context, final Pageable pageable) {
|
||||||
|
throw new RepositoryMethodNotImplementedException(SubmissionCCLicenseUrlRest.NAME, "findAll");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<SubmissionCCLicenseUrlRest> getDomainClass() {
|
||||||
|
return SubmissionCCLicenseUrlRest.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() {
|
||||||
|
discoverableEndpointsService.register(this, Arrays.asList(
|
||||||
|
new Link("/api/" + SubmissionCCLicenseUrlRest.CATEGORY + "/" +
|
||||||
|
SubmissionCCLicenseUrlRest.NAME + "/search",
|
||||||
|
SubmissionCCLicenseUrlRest.NAME + "-search")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -15,7 +15,7 @@ import org.apache.commons.collections4.CollectionUtils;
|
|||||||
import org.dspace.app.rest.model.ParameterRest;
|
import org.dspace.app.rest.model.ParameterRest;
|
||||||
import org.dspace.app.rest.model.ScriptRest;
|
import org.dspace.app.rest.model.ScriptRest;
|
||||||
import org.dspace.app.rest.projection.Projection;
|
import org.dspace.app.rest.projection.Projection;
|
||||||
import org.dspace.scripts.DSpaceRunnable;
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,18 +23,18 @@ import org.springframework.stereotype.Component;
|
|||||||
* of {@link ScriptRest}
|
* of {@link ScriptRest}
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class ScriptConverter implements DSpaceConverter<DSpaceRunnable, ScriptRest> {
|
public class ScriptConverter implements DSpaceConverter<ScriptConfiguration, ScriptRest> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScriptRest convert(DSpaceRunnable script, Projection projection) {
|
public ScriptRest convert(ScriptConfiguration scriptConfiguration, Projection projection) {
|
||||||
ScriptRest scriptRest = new ScriptRest();
|
ScriptRest scriptRest = new ScriptRest();
|
||||||
scriptRest.setProjection(projection);
|
scriptRest.setProjection(projection);
|
||||||
scriptRest.setDescription(script.getDescription());
|
scriptRest.setDescription(scriptConfiguration.getDescription());
|
||||||
scriptRest.setId(script.getName());
|
scriptRest.setId(scriptConfiguration.getName());
|
||||||
scriptRest.setName(script.getName());
|
scriptRest.setName(scriptConfiguration.getName());
|
||||||
|
|
||||||
List<ParameterRest> parameterRestList = new LinkedList<>();
|
List<ParameterRest> parameterRestList = new LinkedList<>();
|
||||||
for (Option option : CollectionUtils.emptyIfNull(script.getOptions().getOptions())) {
|
for (Option option : CollectionUtils.emptyIfNull(scriptConfiguration.getOptions().getOptions())) {
|
||||||
ParameterRest parameterRest = new ParameterRest();
|
ParameterRest parameterRest = new ParameterRest();
|
||||||
parameterRest.setDescription(option.getDescription());
|
parameterRest.setDescription(option.getDescription());
|
||||||
parameterRest.setName((option.getOpt() != null ? "-" + option.getOpt() : "--" + option.getLongOpt()));
|
parameterRest.setName((option.getOpt() != null ? "-" + option.getOpt() : "--" + option.getLongOpt()));
|
||||||
@@ -49,7 +49,7 @@ public class ScriptConverter implements DSpaceConverter<DSpaceRunnable, ScriptRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<DSpaceRunnable> getModelClass() {
|
public Class<ScriptConfiguration> getModelClass() {
|
||||||
return DSpaceRunnable.class;
|
return ScriptConfiguration.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* 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.dspace.app.rest.model.SubmissionCCLicenseFieldRest;
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseRest;
|
||||||
|
import org.dspace.app.rest.projection.Projection;
|
||||||
|
import org.dspace.license.CCLicense;
|
||||||
|
import org.dspace.license.CCLicenseField;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This converter is responsible for transforming the model representation of an CCLicense to the REST
|
||||||
|
* representation of an CCLicense and vice versa
|
||||||
|
**/
|
||||||
|
@Component
|
||||||
|
public class SubmissionCCLicenseConverter implements DSpaceConverter<CCLicense, SubmissionCCLicenseRest> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConverterService converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a CCLicense to its REST representation
|
||||||
|
* @param modelObject - the CCLicense to convert
|
||||||
|
* @param projection - the projection
|
||||||
|
* @return the corresponding SubmissionCCLicenseRest object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SubmissionCCLicenseRest convert(final CCLicense modelObject, final Projection projection) {
|
||||||
|
SubmissionCCLicenseRest submissionCCLicenseRest = new SubmissionCCLicenseRest();
|
||||||
|
submissionCCLicenseRest.setProjection(projection);
|
||||||
|
submissionCCLicenseRest.setId(modelObject.getLicenseId());
|
||||||
|
submissionCCLicenseRest.setName(modelObject.getLicenseName());
|
||||||
|
|
||||||
|
List<CCLicenseField> ccLicenseFieldList = modelObject.getCcLicenseFieldList();
|
||||||
|
List<SubmissionCCLicenseFieldRest> submissionCCLicenseFieldRests = new LinkedList<>();
|
||||||
|
if (ccLicenseFieldList != null) {
|
||||||
|
for (CCLicenseField ccLicenseField : ccLicenseFieldList) {
|
||||||
|
submissionCCLicenseFieldRests.add(converter.toRest(ccLicenseField, projection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
submissionCCLicenseRest.setFields(submissionCCLicenseFieldRests);
|
||||||
|
return submissionCCLicenseRest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<CCLicense> getModelClass() {
|
||||||
|
return CCLicense.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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.converter;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseFieldEnumRest;
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseFieldRest;
|
||||||
|
import org.dspace.app.rest.projection.Projection;
|
||||||
|
import org.dspace.license.CCLicenseField;
|
||||||
|
import org.dspace.license.CCLicenseFieldEnum;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This converter is responsible for transforming the model representation of an CCLicenseField to the REST
|
||||||
|
* representation of an CCLicenseField and vice versa
|
||||||
|
* The CCLicenseField is a sub component of the CCLicense object
|
||||||
|
**/
|
||||||
|
@Component
|
||||||
|
public class SubmissionCCLicenseFieldConverter
|
||||||
|
implements DSpaceConverter<CCLicenseField, SubmissionCCLicenseFieldRest> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConverterService converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a CCLicenseField to its REST representation
|
||||||
|
* @param modelObject - the CCLicenseField to convert
|
||||||
|
* @param projection - the projection
|
||||||
|
* @return the corresponding SubmissionCCLicenseFieldRest object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SubmissionCCLicenseFieldRest convert(final CCLicenseField modelObject, final Projection projection) {
|
||||||
|
SubmissionCCLicenseFieldRest submissionCCLicenseFieldRest = new SubmissionCCLicenseFieldRest();
|
||||||
|
submissionCCLicenseFieldRest.setId(modelObject.getId());
|
||||||
|
submissionCCLicenseFieldRest.setLabel(modelObject.getLabel());
|
||||||
|
submissionCCLicenseFieldRest.setDescription(modelObject.getDescription());
|
||||||
|
|
||||||
|
List<CCLicenseFieldEnum> fieldEnum = modelObject.getFieldEnum();
|
||||||
|
List<SubmissionCCLicenseFieldEnumRest> submissionCCLicenseFieldEnumRests = new LinkedList<>();
|
||||||
|
if (fieldEnum != null) {
|
||||||
|
for (CCLicenseFieldEnum ccLicenseFieldEnum : fieldEnum) {
|
||||||
|
submissionCCLicenseFieldEnumRests.add(converter.toRest(ccLicenseFieldEnum, projection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
submissionCCLicenseFieldRest.setEnums(submissionCCLicenseFieldEnumRests);
|
||||||
|
return submissionCCLicenseFieldRest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<CCLicenseField> getModelClass() {
|
||||||
|
return CCLicenseField.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* 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.SubmissionCCLicenseFieldEnumRest;
|
||||||
|
import org.dspace.app.rest.projection.Projection;
|
||||||
|
import org.dspace.license.CCLicenseFieldEnum;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This converter is responsible for transforming the model representation of an CCLicenseFieldEnum to the REST
|
||||||
|
* representation of an CCLicenseFieldEnum and vice versa
|
||||||
|
* The CCLicenseFieldEnum is a sub component of the CCLicenseField object
|
||||||
|
**/
|
||||||
|
@Component
|
||||||
|
public class SubmissionCCLicenseFieldEnumConverter
|
||||||
|
implements DSpaceConverter<CCLicenseFieldEnum, SubmissionCCLicenseFieldEnumRest> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a CCLicenseFieldEnum to its REST representation
|
||||||
|
*
|
||||||
|
* @param modelObject - the CCLicenseField to convert
|
||||||
|
* @param projection - the projection
|
||||||
|
* @return the corresponding SubmissionCCLicenseFieldEnumRest object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SubmissionCCLicenseFieldEnumRest convert(final CCLicenseFieldEnum modelObject, final Projection projection) {
|
||||||
|
SubmissionCCLicenseFieldEnumRest submissionCCLicenseFieldEnumRest = new SubmissionCCLicenseFieldEnumRest();
|
||||||
|
submissionCCLicenseFieldEnumRest.setId(modelObject.getId());
|
||||||
|
submissionCCLicenseFieldEnumRest.setLabel(modelObject.getLabel());
|
||||||
|
submissionCCLicenseFieldEnumRest.setDescription(modelObject.getDescription());
|
||||||
|
|
||||||
|
return submissionCCLicenseFieldEnumRest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<CCLicenseFieldEnum> getModelClass() {
|
||||||
|
return CCLicenseFieldEnum.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.converter;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseUrlRest;
|
||||||
|
import org.dspace.app.rest.model.wrapper.SubmissionCCLicenseUrl;
|
||||||
|
import org.dspace.app.rest.projection.Projection;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This converter is responsible for transforming a Submission CC License Url String to the REST
|
||||||
|
* representation SubmissionCCLicenseUrlRest and vice versa
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SubmissionCCLicenseUrlConverter
|
||||||
|
implements DSpaceConverter<SubmissionCCLicenseUrl, SubmissionCCLicenseUrlRest> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a Submission CC License Url String to its REST representation
|
||||||
|
* @param modelObject - the CC License Url object to convert
|
||||||
|
* @param projection - the projection
|
||||||
|
* @return the corresponding SubmissionCCLicenseUrlRest object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SubmissionCCLicenseUrlRest convert(SubmissionCCLicenseUrl modelObject, Projection projection) {
|
||||||
|
SubmissionCCLicenseUrlRest submissionCCLicenseUrlRest = new SubmissionCCLicenseUrlRest();
|
||||||
|
submissionCCLicenseUrlRest.setUrl(modelObject.getUrl());
|
||||||
|
submissionCCLicenseUrlRest.setId(modelObject.getId());
|
||||||
|
|
||||||
|
return submissionCCLicenseUrlRest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<SubmissionCCLicenseUrl> getModelClass() {
|
||||||
|
return SubmissionCCLicenseUrl.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -29,6 +29,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
|
|||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
import org.springframework.web.context.request.WebRequest;
|
import org.springframework.web.context.request.WebRequest;
|
||||||
|
import org.springframework.web.multipart.MultipartException;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,8 +55,8 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExceptionHandler(IllegalArgumentException.class)
|
@ExceptionHandler({IllegalArgumentException.class, MultipartException.class})
|
||||||
protected void handleIllegalArgumentException(HttpServletRequest request, HttpServletResponse response,
|
protected void handleWrongRequestException(HttpServletRequest request, HttpServletResponse response,
|
||||||
Exception ex) throws IOException {
|
Exception ex) throws IOException {
|
||||||
sendErrorResponse(request, response, ex, ex.getMessage(), HttpServletResponse.SC_BAD_REQUEST);
|
sendErrorResponse(request, response, ex, ex.getMessage(), HttpServletResponse.SC_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
@@ -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.app.rest.link.process;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.RestResourceController;
|
||||||
|
import org.dspace.app.rest.link.HalLinkFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This abstract class offers an easily extendable HalLinkFactory class to use methods on the RestResourceController
|
||||||
|
* and make it more easy to read or define which methods should be found in the getMethodOn methods when building links
|
||||||
|
* @param <T> This parameter should be of type {@link org.dspace.app.rest.model.hateoas.HALResource}
|
||||||
|
*/
|
||||||
|
public abstract class ProcessHalLinkFactory<T> extends HalLinkFactory<T, RestResourceController> {
|
||||||
|
}
|
@@ -10,7 +10,6 @@ package org.dspace.app.rest.link.process;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import org.dspace.app.rest.RestResourceController;
|
import org.dspace.app.rest.RestResourceController;
|
||||||
import org.dspace.app.rest.link.HalLinkFactory;
|
|
||||||
import org.dspace.app.rest.model.hateoas.ProcessResource;
|
import org.dspace.app.rest.model.hateoas.ProcessResource;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -19,14 +18,15 @@ import org.springframework.hateoas.Link;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class will provide the ProcessResource with links
|
* This HalLinkFactory provides the {@link ProcessResource} with links
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class ProcessResourceHalLinkFactory extends HalLinkFactory<ProcessResource, RestResourceController> {
|
public class ProcessResourceHalLinkFactory extends ProcessHalLinkFactory<ProcessResource> {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConfigurationService configurationService;
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void addLinks(ProcessResource halResource, Pageable pageable, LinkedList<Link> list) throws Exception {
|
protected void addLinks(ProcessResource halResource, Pageable pageable, LinkedList<Link> list) throws Exception {
|
||||||
String dspaceServerUrl = configurationService.getProperty("dspace.server.url");
|
String dspaceServerUrl = configurationService.getProperty("dspace.server.url");
|
||||||
list.add(
|
list.add(
|
||||||
@@ -34,10 +34,12 @@ public class ProcessResourceHalLinkFactory extends HalLinkFactory<ProcessResourc
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected Class<RestResourceController> getControllerClass() {
|
protected Class<RestResourceController> getControllerClass() {
|
||||||
return RestResourceController.class;
|
return RestResourceController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected Class<ProcessResource> getResourceClass() {
|
protected Class<ProcessResource> getResourceClass() {
|
||||||
return ProcessResource.class;
|
return ProcessResource.class;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.link.process;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.RestResourceController;
|
||||||
|
import org.dspace.app.rest.link.HalLinkFactory;
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseUrlRest;
|
||||||
|
import org.dspace.app.rest.model.hateoas.SubmissionCCLicenseUrlResource;
|
||||||
|
import org.dspace.services.RequestService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.hateoas.Link;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class will provide the SubmissionCCLicenseUrlResource with links
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SubmissionCCLicenseUrlResourceHalLinkFactory
|
||||||
|
extends HalLinkFactory<SubmissionCCLicenseUrlResource, RestResourceController> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
RequestService requestService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a self link based on the search parameters
|
||||||
|
*
|
||||||
|
* @param halResource - The halResource
|
||||||
|
* @param pageable - The page information
|
||||||
|
* @param list - The list of present links
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void addLinks(SubmissionCCLicenseUrlResource halResource, final Pageable pageable,
|
||||||
|
LinkedList<Link> list)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
halResource.removeLinks();
|
||||||
|
Map<String, String[]> parameterMap = requestService.getCurrentRequest().getHttpServletRequest()
|
||||||
|
.getParameterMap();
|
||||||
|
|
||||||
|
|
||||||
|
UriComponentsBuilder uriComponentsBuilder = uriBuilder(getMethodOn().executeSearchMethods(
|
||||||
|
SubmissionCCLicenseUrlRest.CATEGORY, SubmissionCCLicenseUrlRest.PLURAL, "rightsByQuestions", null, null,
|
||||||
|
null, null, new LinkedMultiValueMap<>()));
|
||||||
|
for (String key : parameterMap.keySet()) {
|
||||||
|
uriComponentsBuilder.queryParam(key, parameterMap.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
list.add(buildLink("self", uriComponentsBuilder.build().toUriString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<RestResourceController> getControllerClass() {
|
||||||
|
return RestResourceController.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<SubmissionCCLicenseUrlResource> getResourceClass() {
|
||||||
|
return SubmissionCCLicenseUrlResource.class;
|
||||||
|
}
|
||||||
|
}
|
@@ -25,16 +25,16 @@ public class ParameterRest {
|
|||||||
*/
|
*/
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
/**
|
|
||||||
* The long name of the parameter
|
|
||||||
*/
|
|
||||||
private String nameLong;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boolean indicating whether the parameter is mandatory or not
|
* Boolean indicating whether the parameter is mandatory or not
|
||||||
*/
|
*/
|
||||||
private boolean mandatory;
|
private boolean mandatory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The long name of the parameter
|
||||||
|
*/
|
||||||
|
private String nameLong;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.RestResourceController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides a way to list the filetypes present in a given Process by showing them as a list of Strings
|
||||||
|
* It'll be used by {@link org.dspace.app.rest.repository.ProcessFileTypesLinkRepository}
|
||||||
|
*/
|
||||||
|
public class ProcessFileTypesRest extends BaseObjectRest<String> {
|
||||||
|
|
||||||
|
public static final String NAME = "filetypes";
|
||||||
|
public static final String PLURAL_NAME = "filetypes";
|
||||||
|
public static final String CATEGORY = RestAddressableModel.SYSTEM;
|
||||||
|
|
||||||
|
private List<String> values;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the values
|
||||||
|
* @return the values value of this ProcessFileTypesRest
|
||||||
|
*/
|
||||||
|
public List<String> getValues() {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the values
|
||||||
|
* @param values The values to be set on this ProcessFileTypesRest
|
||||||
|
*/
|
||||||
|
public void setValues(List<String> values) {
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a value to the list of FileType Strings
|
||||||
|
* @param value The value to be added
|
||||||
|
*/
|
||||||
|
public void addValue(String value) {
|
||||||
|
if (values == null) {
|
||||||
|
values = new LinkedList<>();
|
||||||
|
}
|
||||||
|
values.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCategory() {
|
||||||
|
return CATEGORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getController() {
|
||||||
|
return RestResourceController.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
}
|
@@ -20,12 +20,23 @@ import org.dspace.scripts.Process;
|
|||||||
/**
|
/**
|
||||||
* This class serves as a REST representation for the {@link Process} class
|
* This class serves as a REST representation for the {@link Process} class
|
||||||
*/
|
*/
|
||||||
|
@LinksRest(links = {
|
||||||
|
@LinkRest(
|
||||||
|
name = ProcessRest.FILES,
|
||||||
|
method = "getFilesFromProcess"
|
||||||
|
),
|
||||||
|
@LinkRest(
|
||||||
|
name = ProcessRest.FILE_TYPES,
|
||||||
|
method = "getFileTypesFromProcess"
|
||||||
|
)
|
||||||
|
})
|
||||||
public class ProcessRest extends BaseObjectRest<Integer> {
|
public class ProcessRest extends BaseObjectRest<Integer> {
|
||||||
public static final String NAME = "process";
|
public static final String NAME = "process";
|
||||||
public static final String PLURAL_NAME = "processes";
|
public static final String PLURAL_NAME = "processes";
|
||||||
public static final String CATEGORY = RestAddressableModel.SYSTEM;
|
public static final String CATEGORY = RestAddressableModel.SYSTEM;
|
||||||
|
|
||||||
|
public static final String FILES = "files";
|
||||||
|
public static final String FILE_TYPES = "filetypes";
|
||||||
public String getCategory() {
|
public String getCategory() {
|
||||||
return CATEGORY;
|
return CATEGORY;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the REST representation of the CCLicenseFieldEnum model object and acts as a data sub object
|
||||||
|
* for the SubmissionCCLicenseFieldRest class.
|
||||||
|
* Refer to {@link org.dspace.license.CCLicenseFieldEnum} for explanation of the properties
|
||||||
|
*/
|
||||||
|
public class SubmissionCCLicenseFieldEnumRest {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String label;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLabel(final String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(final String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the REST representation of the CCLicenseField model object and acts as a data sub object
|
||||||
|
* for the SubmissionCCLicenseRest class.
|
||||||
|
* Refer to {@link org.dspace.license.CCLicenseField} for explanation of the properties
|
||||||
|
*/
|
||||||
|
public class SubmissionCCLicenseFieldRest {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private List<SubmissionCCLicenseFieldEnumRest> enums;
|
||||||
|
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLabel(final String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(final String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SubmissionCCLicenseFieldEnumRest> getEnums() {
|
||||||
|
return enums;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnums(final List<SubmissionCCLicenseFieldEnumRest> enums) {
|
||||||
|
this.enums = enums;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.dspace.app.rest.RestResourceController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the REST representation of the CCLicense model object and acts as a data object
|
||||||
|
* for the SubmissionCCLicenseResource class.
|
||||||
|
* Refer to {@link org.dspace.license.CCLicense} for explanation of the properties
|
||||||
|
*/
|
||||||
|
public class SubmissionCCLicenseRest extends BaseObjectRest<String> {
|
||||||
|
public static final String NAME = "submissioncclicense";
|
||||||
|
public static final String PLURAL = "submissioncclicenses";
|
||||||
|
|
||||||
|
public static final String CATEGORY = RestAddressableModel.CONFIGURATION;
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private List<SubmissionCCLicenseFieldRest> fields;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SubmissionCCLicenseFieldRest> getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFields(final List<SubmissionCCLicenseFieldRest> fields) {
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public String getCategory() {
|
||||||
|
return CATEGORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
public String getType() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonIgnore
|
||||||
|
public Class getController() {
|
||||||
|
return RestResourceController.class;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.dspace.app.rest.RestResourceController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the REST representation of the CCLicense URL String object and acts as a data object
|
||||||
|
* for the SubmissionCCLicenseUrlRest class.
|
||||||
|
*/
|
||||||
|
public class SubmissionCCLicenseUrlRest extends BaseObjectRest<String> {
|
||||||
|
public static final String NAME = "submissioncclicenseUrl";
|
||||||
|
public static final String PLURAL = "submissioncclicenseUrls";
|
||||||
|
public static final String CATEGORY = RestAddressableModel.CONFIGURATION;
|
||||||
|
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(final String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
public String getType() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCategory() {
|
||||||
|
return SubmissionCCLicenseUrlRest.CATEGORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonIgnore
|
||||||
|
public Class getController() {
|
||||||
|
return RestResourceController.class;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model.hateoas;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.ProcessFileTypesRest;
|
||||||
|
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource object for {@link ProcessFileTypesRest}
|
||||||
|
*/
|
||||||
|
@RelNameDSpaceResource(ProcessFileTypesRest.NAME)
|
||||||
|
public class ProcessFileTypesResource extends HALResource<ProcessFileTypesRest> {
|
||||||
|
|
||||||
|
public ProcessFileTypesResource(ProcessFileTypesRest content) {
|
||||||
|
super(content);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model.hateoas;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseRest;
|
||||||
|
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CCLicense HAL Resource. This resource adds the data from the REST object together with embedded objects
|
||||||
|
* and a set of links if applicable
|
||||||
|
*/
|
||||||
|
@RelNameDSpaceResource(SubmissionCCLicenseRest.NAME)
|
||||||
|
public class SubmissionCCLicenseResource extends DSpaceResource<SubmissionCCLicenseRest> {
|
||||||
|
public SubmissionCCLicenseResource(SubmissionCCLicenseRest submissionCCLicenseRest, Utils utils) {
|
||||||
|
super(submissionCCLicenseRest, utils);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model.hateoas;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseUrlRest;
|
||||||
|
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SubmissionCCLicenseUrl HAL Resource. This resource adds the data from the REST object together with embedded objects
|
||||||
|
* and a set of links if applicable
|
||||||
|
*/
|
||||||
|
@RelNameDSpaceResource(SubmissionCCLicenseUrlRest.NAME)
|
||||||
|
public class SubmissionCCLicenseUrlResource extends DSpaceResource<SubmissionCCLicenseUrlRest> {
|
||||||
|
public SubmissionCCLicenseUrlResource(SubmissionCCLicenseUrlRest submissionCCLicenseUrlRest, Utils utils) {
|
||||||
|
super(submissionCCLicenseUrlRest, utils);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model.step;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java Bean to expose the section creativecommons representing the CC License during in progress submission.
|
||||||
|
*/
|
||||||
|
public class DataCCLicense implements SectionData {
|
||||||
|
|
||||||
|
private String uri;
|
||||||
|
|
||||||
|
private String rights;
|
||||||
|
|
||||||
|
private BitstreamRest file;
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(final String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRights() {
|
||||||
|
return rights;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRights(final String rights) {
|
||||||
|
this.rights = rights;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitstreamRest getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFile(final BitstreamRest file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.model.wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a model implementation for {@link org.dspace.app.rest.model.SubmissionCCLicenseUrlRest}
|
||||||
|
* This will simply store a url and an id. it'll be used to create an object with these variables out of information
|
||||||
|
* that came from the back-end. This object will then be used in the
|
||||||
|
* {@link org.dspace.app.rest.converter.SubmissionCCLicenseUrlConverter} to turn it into its REST object
|
||||||
|
*/
|
||||||
|
public class SubmissionCCLicenseUrl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The url for ths object
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
/**
|
||||||
|
* The id for this object
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor with two parameters, url and id
|
||||||
|
* @param url The url of this object
|
||||||
|
* @param id The id of this object
|
||||||
|
*/
|
||||||
|
public SubmissionCCLicenseUrl(String url, String id) {
|
||||||
|
this.url = url;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the url
|
||||||
|
* @return the url value of this SubmissionCCLicenseUrl
|
||||||
|
*/
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the url
|
||||||
|
* @param url The url to be set on this SubmissionCCLicenseUrl
|
||||||
|
*/
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic getter for the id
|
||||||
|
* @return the id value of this SubmissionCCLicenseUrl
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the id
|
||||||
|
* @param id The id to be set on this SubmissionCCLicenseUrl
|
||||||
|
*/
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
@@ -10,17 +10,14 @@ package org.dspace.app.rest.repository;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
|
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||||
import org.dspace.app.rest.model.BitstreamRest;
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
import org.dspace.app.rest.model.BundleRest;
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
import org.dspace.app.rest.model.patch.Patch;
|
import org.dspace.app.rest.model.patch.Patch;
|
||||||
import org.dspace.app.rest.projection.Projection;
|
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.authorize.service.AuthorizeService;
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
@@ -34,7 +31,6 @@ import org.dspace.content.service.CommunityService;
|
|||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@@ -71,7 +67,7 @@ public class BitstreamRestRepository extends DSpaceObjectRestRepository<Bitstrea
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PreAuthorize("hasPermission(#id, 'BITSTREAM', 'READ')")
|
@PreAuthorize("hasPermission(#id, 'BITSTREAM', 'METADATA_READ')")
|
||||||
public BitstreamRest findOne(Context context, UUID id) {
|
public BitstreamRest findOne(Context context, UUID id) {
|
||||||
Bitstream bit = null;
|
Bitstream bit = null;
|
||||||
try {
|
try {
|
||||||
@@ -95,22 +91,7 @@ public class BitstreamRestRepository extends DSpaceObjectRestRepository<Bitstrea
|
|||||||
@Override
|
@Override
|
||||||
@PreAuthorize("hasAuthority('ADMIN')")
|
@PreAuthorize("hasAuthority('ADMIN')")
|
||||||
public Page<BitstreamRest> findAll(Context context, Pageable pageable) {
|
public Page<BitstreamRest> findAll(Context context, Pageable pageable) {
|
||||||
List<Bitstream> bit = new ArrayList<Bitstream>();
|
throw new RepositoryMethodNotImplementedException(BitstreamRest.NAME, "findAll");
|
||||||
Iterator<Bitstream> it = null;
|
|
||||||
int total = 0;
|
|
||||||
try {
|
|
||||||
total = bs.countTotal(context);
|
|
||||||
it = bs.findAll(context, pageable.getPageSize(), Math.toIntExact(pageable.getOffset()));
|
|
||||||
while (it.hasNext()) {
|
|
||||||
bit.add(it.next());
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
Projection projection = utils.obtainProjection();
|
|
||||||
Page<BitstreamRest> page = new PageImpl<>(bit, pageable, total)
|
|
||||||
.map((bitstream) -> converter.toRest(bitstream, projection));
|
|
||||||
return page;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.repository;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.ProcessFileTypesRest;
|
||||||
|
import org.dspace.app.rest.model.ProcessRest;
|
||||||
|
import org.dspace.app.rest.projection.Projection;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.Process;
|
||||||
|
import org.dspace.scripts.service.ProcessService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This LinkRepository will deal with calls to the /filetypes endpoint of a given Process.
|
||||||
|
* It'll retrieve all the bitstreams for the given Process and return a {@link ProcessFileTypesRest} object that holds
|
||||||
|
* a list of Strings where each String represents a unique fileType of the Bitstreams for that Process
|
||||||
|
*/
|
||||||
|
@Component(ProcessRest.CATEGORY + "." + ProcessRest.NAME + "." + ProcessRest.FILE_TYPES)
|
||||||
|
public class ProcessFileTypesLinkRepository extends AbstractDSpaceRestRepository implements LinkRestRepository {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ProcessService processService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will be the admin only endpoint that returns the {@link ProcessFileTypesRest} constructed with the values
|
||||||
|
* found in the Bitstreams of the Process with the given ProcessId
|
||||||
|
* @param request The relevant request
|
||||||
|
* @param processId The processId of the Process to be used
|
||||||
|
* @param optionalPageable Paging if applicable
|
||||||
|
* @param projection The current projection
|
||||||
|
* @return The {@link ProcessFileTypesRest} created from the Bitstreams of the given Process
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
* @throws AuthorizeException If something goes wrong
|
||||||
|
*/
|
||||||
|
@PreAuthorize("hasAuthority('ADMIN')")
|
||||||
|
public ProcessFileTypesRest getFileTypesFromProcess(@Nullable HttpServletRequest request,
|
||||||
|
Integer processId,
|
||||||
|
@Nullable Pageable optionalPageable,
|
||||||
|
Projection projection) throws SQLException, AuthorizeException {
|
||||||
|
|
||||||
|
Context context = obtainContext();
|
||||||
|
Process process = processService.find(context, processId);
|
||||||
|
if (process == null) {
|
||||||
|
throw new ResourceNotFoundException("Process with id " + processId + " was not found");
|
||||||
|
}
|
||||||
|
List<String> fileTypes = processService.getFileTypesForProcessBitstreams(context, process);
|
||||||
|
ProcessFileTypesRest processFileTypesRest = new ProcessFileTypesRest();
|
||||||
|
processFileTypesRest.setId("filetypes-" + processId);
|
||||||
|
processFileTypesRest.setValues(fileTypes);
|
||||||
|
return processFileTypesRest;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.repository;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
|
import org.dspace.app.rest.model.ProcessRest;
|
||||||
|
import org.dspace.app.rest.projection.Projection;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the {@link LinkRestRepository} implementation that takes care of retrieving the list of
|
||||||
|
* {@link org.dspace.content.Bitstream} objects for the Process endpoints
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component(ProcessRest.CATEGORY + "." + ProcessRest.NAME + "." + ProcessRest.FILES)
|
||||||
|
public class ProcessFilesLinkRepository extends AbstractDSpaceRestRepository implements LinkRestRepository {
|
||||||
|
|
||||||
|
private static final Logger log = LogManager.getLogger();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ProcessRestRepository processRestRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will retrieve all the files from the process
|
||||||
|
* @param request The current request
|
||||||
|
* @param processId The processId for the Process to use
|
||||||
|
* @param optionalPageable Pageable if applicable
|
||||||
|
* @param projection Projection if applicable
|
||||||
|
* @return A list of {@link BitstreamRest} objects filled
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
* @throws AuthorizeException If something goes wrong
|
||||||
|
*/
|
||||||
|
@PreAuthorize("hasAuthority('ADMIN')")
|
||||||
|
public Page<BitstreamRest> getFilesFromProcess(@Nullable HttpServletRequest request,
|
||||||
|
Integer processId,
|
||||||
|
@Nullable Pageable optionalPageable,
|
||||||
|
Projection projection) throws SQLException, AuthorizeException {
|
||||||
|
|
||||||
|
List<BitstreamRest> list = processRestRepository.getProcessBitstreams(processId);
|
||||||
|
Pageable pageable = utils.getPageable(optionalPageable);
|
||||||
|
return utils.getPage(list, pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will retrieve a bitstream for the given processId for the given fileType
|
||||||
|
* @param request The current request
|
||||||
|
* @param processId The processId for the process to search in
|
||||||
|
* @param fileType The filetype that the bitstream has to be
|
||||||
|
* @param pageable Pageable if applicable
|
||||||
|
* @param projection The current projection
|
||||||
|
* @return The BitstreamRest object that corresponds with the Process and type
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
* @throws AuthorizeException If something goes wrong
|
||||||
|
*/
|
||||||
|
@PreAuthorize("hasPermission(#processId, 'PROCESS', 'READ')")
|
||||||
|
public BitstreamRest getResource(HttpServletRequest request, String processId, String fileType,
|
||||||
|
Pageable pageable, Projection projection)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
if (log.isTraceEnabled()) {
|
||||||
|
log.trace("Retrieving Files with type " + fileType + " from Process with ID: " + processId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return processRestRepository.getProcessBitstreamByType(Integer.parseInt(processId), fileType);
|
||||||
|
}
|
||||||
|
}
|
@@ -7,17 +7,27 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.rest.repository;
|
package org.dspace.app.rest.repository;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
import org.dspace.app.rest.converter.ConverterService;
|
||||||
|
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||||
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
import org.dspace.app.rest.model.ProcessRest;
|
import org.dspace.app.rest.model.ProcessRest;
|
||||||
|
import org.dspace.app.rest.projection.Projection;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.scripts.Process;
|
import org.dspace.scripts.Process;
|
||||||
import org.dspace.scripts.service.ProcessService;
|
import org.dspace.scripts.service.ProcessService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -32,6 +42,14 @@ public class ProcessRestRepository extends DSpaceRestRepository<ProcessRest, Int
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ProcessService processService;
|
private ProcessService processService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConverterService converterService;
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PreAuthorize("hasPermission(#id, 'PROCESS', 'READ')")
|
@PreAuthorize("hasPermission(#id, 'PROCESS', 'READ')")
|
||||||
public ProcessRest findOne(Context context, Integer id) {
|
public ProcessRest findOne(Context context, Integer id) {
|
||||||
@@ -60,6 +78,63 @@ public class ProcessRestRepository extends DSpaceRestRepository<ProcessRest, Int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls on the getBitstreams method to retrieve all the Bitstreams of this process
|
||||||
|
* @param processId The processId of the Process to retrieve the Bitstreams for
|
||||||
|
* @return The list of Bitstreams of the given Process
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
* @throws AuthorizeException If something goes wrong
|
||||||
|
*/
|
||||||
|
public List<BitstreamRest> getProcessBitstreams(Integer processId) throws SQLException, AuthorizeException {
|
||||||
|
Context context = obtainContext();
|
||||||
|
Process process = getProcess(processId, context);
|
||||||
|
List<Bitstream> bitstreams = processService.getBitstreams(context, process);
|
||||||
|
return bitstreams.stream()
|
||||||
|
.map(bitstream -> (BitstreamRest) converterService.toRest(bitstream, Projection.DEFAULT))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Process getProcess(Integer processId, Context context) throws SQLException, AuthorizeException {
|
||||||
|
Process process = processService.find(context, processId);
|
||||||
|
if (process == null) {
|
||||||
|
throw new ResourceNotFoundException("Process with id " + processId + " was not found");
|
||||||
|
}
|
||||||
|
if ((context.getCurrentUser() == null) || (!context.getCurrentUser()
|
||||||
|
.equals(process.getEPerson()) && !authorizeService
|
||||||
|
.isAdmin(context))) {
|
||||||
|
throw new AuthorizeException("The current user is not eligible to view the process with id: " + processId);
|
||||||
|
}
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the Bitstream in the given Process of a given type
|
||||||
|
* @param processId The processId of the Process to be used
|
||||||
|
* @param type The type of bitstreams to be returned, if null it'll return all the bitstreams
|
||||||
|
* @return The bitstream for the given parameters
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
* @throws AuthorizeException If something goes wrong
|
||||||
|
*/
|
||||||
|
public BitstreamRest getProcessBitstreamByType(Integer processId, String type)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
Context context = obtainContext();
|
||||||
|
Process process = getProcess(processId, context);
|
||||||
|
Bitstream bitstream = processService.getBitstream(context, process, type);
|
||||||
|
|
||||||
|
return converterService.toRest(bitstream, utils.obtainProjection());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void delete(Context context, Integer integer)
|
||||||
|
throws AuthorizeException, RepositoryMethodNotImplementedException {
|
||||||
|
try {
|
||||||
|
processService.delete(context, processService.find(context, integer));
|
||||||
|
} catch (SQLException | IOException e) {
|
||||||
|
log.error("Something went wrong trying to find Process with id: " + integer, e);
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<ProcessRest> getDomainClass() {
|
public Class<ProcessRest> getDomainClass() {
|
||||||
return ProcessRest.class;
|
return ProcessRest.class;
|
||||||
|
@@ -22,6 +22,7 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.app.rest.converter.DSpaceRunnableParameterConverter;
|
import org.dspace.app.rest.converter.DSpaceRunnableParameterConverter;
|
||||||
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.model.ParameterValueRest;
|
import org.dspace.app.rest.model.ParameterValueRest;
|
||||||
import org.dspace.app.rest.model.ProcessRest;
|
import org.dspace.app.rest.model.ProcessRest;
|
||||||
import org.dspace.app.rest.model.ScriptRest;
|
import org.dspace.app.rest.model.ScriptRest;
|
||||||
@@ -30,6 +31,7 @@ import org.dspace.authorize.AuthorizeException;
|
|||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||||
import org.dspace.scripts.DSpaceRunnable;
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
import org.dspace.scripts.service.ScriptService;
|
import org.dspace.scripts.service.ScriptService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@@ -37,6 +39,7 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the REST repository dealing with the Script logic
|
* This is the REST repository dealing with the Script logic
|
||||||
@@ -56,10 +59,10 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
|||||||
@PreAuthorize("permitAll()")
|
@PreAuthorize("permitAll()")
|
||||||
public ScriptRest findOne(Context context, String name) {
|
public ScriptRest findOne(Context context, String name) {
|
||||||
|
|
||||||
DSpaceRunnable dSpaceRunnable = scriptService.getScriptForName(name);
|
ScriptConfiguration scriptConfiguration = scriptService.getScriptConfiguration(name);
|
||||||
if (dSpaceRunnable != null) {
|
if (scriptConfiguration != null) {
|
||||||
if (dSpaceRunnable.isAllowedToExecute(context)) {
|
if (scriptConfiguration.isAllowedToExecute(context)) {
|
||||||
return converter.toRest(dSpaceRunnable, utils.obtainProjection());
|
return converter.toRest(scriptConfiguration, utils.obtainProjection());
|
||||||
} else {
|
} else {
|
||||||
throw new AccessDeniedException("The current user was not authorized to access this script");
|
throw new AccessDeniedException("The current user was not authorized to access this script");
|
||||||
}
|
}
|
||||||
@@ -69,8 +72,8 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<ScriptRest> findAll(Context context, Pageable pageable) {
|
public Page<ScriptRest> findAll(Context context, Pageable pageable) {
|
||||||
List<DSpaceRunnable> dSpaceRunnables = scriptService.getDSpaceRunnables(context);
|
List<ScriptConfiguration> scriptConfigurations = scriptService.getScriptConfigurations(context);
|
||||||
return converter.toRestPage(dSpaceRunnables, pageable, utils.obtainProjection());
|
return converter.toRestPage(scriptConfigurations, pageable, utils.obtainProjection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,12 +89,12 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
|||||||
* @throws SQLException If something goes wrong
|
* @throws SQLException If something goes wrong
|
||||||
* @throws IOException If something goes wrong
|
* @throws IOException If something goes wrong
|
||||||
*/
|
*/
|
||||||
public ProcessRest startProcess(Context context, String scriptName) throws SQLException,
|
public ProcessRest startProcess(Context context, String scriptName, List<MultipartFile> files) throws SQLException,
|
||||||
IOException, AuthorizeException {
|
IOException, AuthorizeException, IllegalAccessException, InstantiationException {
|
||||||
String properties = requestService.getCurrentRequest().getServletRequest().getParameter("properties");
|
String properties = requestService.getCurrentRequest().getServletRequest().getParameter("properties");
|
||||||
List<DSpaceCommandLineParameter> dSpaceCommandLineParameters =
|
List<DSpaceCommandLineParameter> dSpaceCommandLineParameters =
|
||||||
processPropertiesToDSpaceCommandLineParameters(properties);
|
processPropertiesToDSpaceCommandLineParameters(properties);
|
||||||
DSpaceRunnable scriptToExecute = scriptService.getScriptForName(scriptName);
|
ScriptConfiguration scriptToExecute = scriptService.getScriptConfiguration(scriptName);
|
||||||
if (scriptToExecute == null) {
|
if (scriptToExecute == null) {
|
||||||
throw new DSpaceBadRequestException("The script for name: " + scriptName + " wasn't found");
|
throw new DSpaceBadRequestException("The script for name: " + scriptName + " wasn't found");
|
||||||
}
|
}
|
||||||
@@ -101,7 +104,7 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
|||||||
RestDSpaceRunnableHandler restDSpaceRunnableHandler = new RestDSpaceRunnableHandler(
|
RestDSpaceRunnableHandler restDSpaceRunnableHandler = new RestDSpaceRunnableHandler(
|
||||||
context.getCurrentUser(), scriptName, dSpaceCommandLineParameters);
|
context.getCurrentUser(), scriptName, dSpaceCommandLineParameters);
|
||||||
List<String> args = constructArgs(dSpaceCommandLineParameters);
|
List<String> args = constructArgs(dSpaceCommandLineParameters);
|
||||||
runDSpaceScript(scriptToExecute, restDSpaceRunnableHandler, args);
|
runDSpaceScript(files, context, scriptToExecute, restDSpaceRunnableHandler, args);
|
||||||
return converter.toRest(restDSpaceRunnableHandler.getProcess(context), utils.obtainProjection());
|
return converter.toRest(restDSpaceRunnableHandler.getProcess(context), utils.obtainProjection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,13 +134,17 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runDSpaceScript(DSpaceRunnable scriptToExecute,
|
private void runDSpaceScript(List<MultipartFile> files, Context context, ScriptConfiguration scriptToExecute,
|
||||||
RestDSpaceRunnableHandler restDSpaceRunnableHandler, List<String> args) {
|
RestDSpaceRunnableHandler restDSpaceRunnableHandler, List<String> args)
|
||||||
|
throws IOException, SQLException, AuthorizeException, InstantiationException, IllegalAccessException {
|
||||||
|
DSpaceRunnable dSpaceRunnable = scriptService.createDSpaceRunnableForScriptConfiguration(scriptToExecute);
|
||||||
try {
|
try {
|
||||||
scriptToExecute.initialize(args.toArray(new String[0]), restDSpaceRunnableHandler);
|
dSpaceRunnable.initialize(args.toArray(new String[0]), restDSpaceRunnableHandler, context.getCurrentUser());
|
||||||
restDSpaceRunnableHandler.schedule(scriptToExecute);
|
checkFileNames(dSpaceRunnable, files);
|
||||||
|
processFiles(context, restDSpaceRunnableHandler, files);
|
||||||
|
restDSpaceRunnableHandler.schedule(dSpaceRunnable);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
scriptToExecute.printHelp();
|
dSpaceRunnable.printHelp();
|
||||||
restDSpaceRunnableHandler
|
restDSpaceRunnableHandler
|
||||||
.handleException(
|
.handleException(
|
||||||
"Failed to parse the arguments given to the script with name: " + scriptToExecute.getName()
|
"Failed to parse the arguments given to the script with name: " + scriptToExecute.getName()
|
||||||
@@ -145,4 +152,37 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processFiles(Context context, RestDSpaceRunnableHandler restDSpaceRunnableHandler,
|
||||||
|
List<MultipartFile> files)
|
||||||
|
throws IOException, SQLException, AuthorizeException {
|
||||||
|
for (MultipartFile file : files) {
|
||||||
|
restDSpaceRunnableHandler
|
||||||
|
.writeFilestream(context, file.getOriginalFilename(), file.getInputStream(), "inputfile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks if the files referenced in the options are actually present for the request
|
||||||
|
* If this isn't the case, we'll abort the script now instead of creating issues later on
|
||||||
|
* @param dSpaceRunnable The script that we'll attempt to run
|
||||||
|
* @param files The list of files in the request
|
||||||
|
*/
|
||||||
|
private void checkFileNames(DSpaceRunnable dSpaceRunnable, List<MultipartFile> files) {
|
||||||
|
List<String> fileNames = new LinkedList<>();
|
||||||
|
for (MultipartFile file : files) {
|
||||||
|
String fileName = file.getOriginalFilename();
|
||||||
|
if (fileNames.contains(fileName)) {
|
||||||
|
throw new UnprocessableEntityException("There are two files with the same name: " + fileName);
|
||||||
|
} else {
|
||||||
|
fileNames.add(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> fileNamesFromOptions = dSpaceRunnable.getFileNamesFromInputStreamOptions();
|
||||||
|
if (!fileNames.containsAll(fileNamesFromOptions)) {
|
||||||
|
throw new UnprocessableEntityException("Files given in properties aren't all present in the request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseRest;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.license.CCLicense;
|
||||||
|
import org.dspace.license.service.CreativeCommonsService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the repository that is responsible to manage CCLicense Rest objects
|
||||||
|
*/
|
||||||
|
@Component(SubmissionCCLicenseRest.CATEGORY + "." + SubmissionCCLicenseRest.NAME)
|
||||||
|
public class SubmissionCCLicenseRestRepository extends DSpaceRestRepository<SubmissionCCLicenseRest, String> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected CreativeCommonsService creativeCommonsService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||||
|
public SubmissionCCLicenseRest findOne(final Context context, final String licenseId) {
|
||||||
|
CCLicense ccLicense = creativeCommonsService.findOne(licenseId);
|
||||||
|
if (ccLicense == null) {
|
||||||
|
throw new ResourceNotFoundException("No CC license could be found for ID: " + licenseId );
|
||||||
|
}
|
||||||
|
return converter.toRest(ccLicense, utils.obtainProjection());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||||
|
public Page<SubmissionCCLicenseRest> findAll(final Context context, final Pageable pageable) {
|
||||||
|
|
||||||
|
List<CCLicense> allCCLicenses = creativeCommonsService.findAllCCLicenses();
|
||||||
|
return converter.toRestPage(allCCLicenses, pageable, utils.obtainProjection());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<SubmissionCCLicenseRest> getDomainClass() {
|
||||||
|
return SubmissionCCLicenseRest.class;
|
||||||
|
}
|
||||||
|
}
|
@@ -292,7 +292,8 @@ public class WorkflowItemRestRepository extends DSpaceRestRepository<WorkflowIte
|
|||||||
AbstractRestProcessingStep stepProcessing =
|
AbstractRestProcessingStep stepProcessing =
|
||||||
(AbstractRestProcessingStep) stepClass.newInstance();
|
(AbstractRestProcessingStep) stepClass.newInstance();
|
||||||
stepProcessing.doPreProcessing(context, source);
|
stepProcessing.doPreProcessing(context, source);
|
||||||
stepProcessing.doPatchProcessing(context, getRequestService().getCurrentRequest(), source, op);
|
stepProcessing.doPatchProcessing(context, getRequestService().getCurrentRequest(),
|
||||||
|
source, op, stepConfig);
|
||||||
stepProcessing.doPostProcessing(context, source);
|
stepProcessing.doPostProcessing(context, source);
|
||||||
} else {
|
} else {
|
||||||
throw new DSpaceBadRequestException(
|
throw new DSpaceBadRequestException(
|
||||||
|
@@ -292,6 +292,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
|||||||
|
|
||||||
private void evaluatePatch(Context context, HttpServletRequest request, WorkspaceItem source, WorkspaceItemRest wsi,
|
private void evaluatePatch(Context context, HttpServletRequest request, WorkspaceItem source, WorkspaceItemRest wsi,
|
||||||
String section, Operation op) {
|
String section, Operation op) {
|
||||||
|
boolean sectionExist = false;
|
||||||
SubmissionConfig submissionConfig = submissionConfigReader
|
SubmissionConfig submissionConfig = submissionConfigReader
|
||||||
.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
|
.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
|
||||||
for (int stepNum = 0; stepNum < submissionConfig.getNumberOfSteps(); stepNum++) {
|
for (int stepNum = 0; stepNum < submissionConfig.getNumberOfSteps(); stepNum++) {
|
||||||
@@ -299,6 +300,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
|||||||
SubmissionStepConfig stepConfig = submissionConfig.getStep(stepNum);
|
SubmissionStepConfig stepConfig = submissionConfig.getStep(stepNum);
|
||||||
|
|
||||||
if (section.equals(stepConfig.getId())) {
|
if (section.equals(stepConfig.getId())) {
|
||||||
|
sectionExist = true;
|
||||||
/*
|
/*
|
||||||
* First, load the step processing class (using the current
|
* First, load the step processing class (using the current
|
||||||
* class loader)
|
* class loader)
|
||||||
@@ -315,7 +317,8 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
|||||||
AbstractRestProcessingStep stepProcessing =
|
AbstractRestProcessingStep stepProcessing =
|
||||||
(AbstractRestProcessingStep) stepClass.newInstance();
|
(AbstractRestProcessingStep) stepClass.newInstance();
|
||||||
stepProcessing.doPreProcessing(context, source);
|
stepProcessing.doPreProcessing(context, source);
|
||||||
stepProcessing.doPatchProcessing(context, getRequestService().getCurrentRequest(), source, op);
|
stepProcessing.doPatchProcessing(context,
|
||||||
|
getRequestService().getCurrentRequest(), source, op, stepConfig);
|
||||||
stepProcessing.doPostProcessing(context, source);
|
stepProcessing.doPostProcessing(context, source);
|
||||||
} else {
|
} else {
|
||||||
throw new DSpaceBadRequestException(
|
throw new DSpaceBadRequestException(
|
||||||
@@ -324,12 +327,18 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
|||||||
" Therefore it cannot be used by the Configurable Submission as the <processing-class>!");
|
" Therefore it cannot be used by the Configurable Submission as the <processing-class>!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
throw new PatchException("Error processing the patch request", e);
|
throw new PatchException("Error processing the patch request", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!sectionExist) {
|
||||||
|
throw new UnprocessableEntityException("The section with name " + section +
|
||||||
|
" does not exist in this submission!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'DELETE')")
|
@PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'DELETE')")
|
||||||
|
@@ -7,16 +7,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.rest.scripts.handler.impl;
|
package org.dspace.app.rest.scripts.handler.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apache.commons.cli.HelpFormatter;
|
import org.apache.commons.cli.HelpFormatter;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.ProcessStatus;
|
import org.dspace.content.ProcessStatus;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.BitstreamService;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||||
@@ -25,6 +32,8 @@ import org.dspace.scripts.Process;
|
|||||||
import org.dspace.scripts.factory.ScriptServiceFactory;
|
import org.dspace.scripts.factory.ScriptServiceFactory;
|
||||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
import org.dspace.scripts.service.ProcessService;
|
import org.dspace.scripts.service.ProcessService;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link DSpaceRunnableHandler} dealing with Scripts started from the REST api
|
* The {@link DSpaceRunnableHandler} dealing with Scripts started from the REST api
|
||||||
@@ -33,6 +42,7 @@ public class RestDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
|||||||
private static final Logger log = org.apache.logging.log4j.LogManager
|
private static final Logger log = org.apache.logging.log4j.LogManager
|
||||||
.getLogger(RestDSpaceRunnableHandler.class);
|
.getLogger(RestDSpaceRunnableHandler.class);
|
||||||
|
|
||||||
|
private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
|
||||||
private ProcessService processService = ScriptServiceFactory.getInstance().getProcessService();
|
private ProcessService processService = ScriptServiceFactory.getInstance().getProcessService();
|
||||||
|
|
||||||
private Integer processId;
|
private Integer processId;
|
||||||
@@ -176,6 +186,31 @@ public class RestDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<InputStream> getFileStream(Context context, String fileName) throws IOException,
|
||||||
|
AuthorizeException {
|
||||||
|
try {
|
||||||
|
Process process = processService.find(context, processId);
|
||||||
|
Bitstream bitstream = processService.getBitstreamByName(context, process, fileName);
|
||||||
|
InputStream inputStream = bitstreamService.retrieve(context, bitstream);
|
||||||
|
if (inputStream == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
} else {
|
||||||
|
return Optional.of(inputStream);
|
||||||
|
}
|
||||||
|
} catch (SQLException sqlException) {
|
||||||
|
log.error("SQL exception while attempting to find process", sqlException);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeFilestream(Context context, String fileName, InputStream inputStream, String type)
|
||||||
|
throws IOException, SQLException, AuthorizeException {
|
||||||
|
Process process = processService.find(context, processId);
|
||||||
|
processService.appendFile(context, process, inputStream, type, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will return the process created by this handler
|
* This method will return the process created by this handler
|
||||||
* @return The Process database object created by this handler
|
* @return The Process database object created by this handler
|
||||||
@@ -196,6 +231,9 @@ public class RestDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
|||||||
* @param script The script to be ran
|
* @param script The script to be ran
|
||||||
*/
|
*/
|
||||||
public void schedule(DSpaceRunnable script) {
|
public void schedule(DSpaceRunnable script) {
|
||||||
|
ThreadPoolTaskExecutor taskExecutor = new DSpace().getServiceManager()
|
||||||
|
.getServiceByName("dspaceRunnableThreadExecutor",
|
||||||
|
ThreadPoolTaskExecutor.class);
|
||||||
Context context = new Context();
|
Context context = new Context();
|
||||||
try {
|
try {
|
||||||
Process process = processService.find(context, processId);
|
Process process = processService.find(context, processId);
|
||||||
@@ -209,6 +247,6 @@ public class RestDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
|||||||
context.abort();
|
context.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
script.run();
|
taskExecutor.execute(script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* 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.security;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.repository.BitstreamRestRepository;
|
||||||
|
import org.dspace.app.rest.utils.ContextUtil;
|
||||||
|
import org.dspace.app.rest.utils.DSpaceObjectUtils;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.Bundle;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.service.BitstreamService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.services.RequestService;
|
||||||
|
import org.dspace.services.model.Request;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by {@link BitstreamRestRepository#findOne(Context, UUID)} to get metadata of private bitstreams even though user
|
||||||
|
* can't access actual file
|
||||||
|
*
|
||||||
|
* @author Maria Verdonck (Atmire) on 15/06/2020
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BitstreamMetadataReadPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BitstreamMetadataReadPermissionEvaluatorPlugin.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RequestService requestService;
|
||||||
|
@Autowired
|
||||||
|
private DSpaceObjectUtils dspaceObjectUtil;
|
||||||
|
@Autowired
|
||||||
|
AuthorizeService authorizeService;
|
||||||
|
@Autowired
|
||||||
|
protected BitstreamService bitstreamService;
|
||||||
|
|
||||||
|
private final static String METADATA_READ_PERMISSION = "METADATA_READ";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
|
||||||
|
Object permission) {
|
||||||
|
if (permission.toString().equalsIgnoreCase(METADATA_READ_PERMISSION) && targetId != null) {
|
||||||
|
Request request = requestService.getCurrentRequest();
|
||||||
|
Context context = ContextUtil.obtainContext(request.getServletRequest());
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID dsoUuid = UUID.fromString(targetId.toString());
|
||||||
|
DSpaceObject dso = dspaceObjectUtil.findDSpaceObject(context, dsoUuid);
|
||||||
|
if (dso instanceof Bitstream) {
|
||||||
|
if (authorizeService.isAdmin(context, dso)) {
|
||||||
|
// Is Admin on bitstream
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (authorizeService.authorizeActionBoolean(context, dso, Constants.READ)) {
|
||||||
|
// Has READ rights on bitstream
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
DSpaceObject bitstreamParentObject = bitstreamService.getParentObject(context, (Bitstream) dso);
|
||||||
|
if (bitstreamParentObject instanceof Item && !((Bitstream) dso).getBundles().isEmpty()) {
|
||||||
|
// If parent is item and it is in a bundle
|
||||||
|
Bundle firstBundle = ((Bitstream) dso).getBundles().get(0);
|
||||||
|
if (authorizeService.authorizeActionBoolean(context, bitstreamParentObject, Constants.READ)
|
||||||
|
&& authorizeService.authorizeActionBoolean(context, firstBundle, Constants.READ)) {
|
||||||
|
// Has READ rights on bitstream's parent item AND first bundle bitstream is in
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
|
||||||
|
DSpaceRestPermission restPermission) {
|
||||||
|
// No need to override, since only user by super.hasPermission(Authentication authentication, Serializable
|
||||||
|
// targetId, String targetType, Object permission) which is overrode above
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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.security;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseRest;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class SubmissionCCLicenseRestEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
|
||||||
|
DSpaceRestPermission restPermission) {
|
||||||
|
if (!StringUtils.equalsIgnoreCase(SubmissionCCLicenseRest.NAME, targetType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* 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.security;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.app.rest.model.SubmissionCCLicenseUrlRest;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class will handle calls made to SubmissionCCLicenseUrlRest endpoints.
|
||||||
|
* It will return true because access can be granted anytime it's linked from another resource
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SubmissionCCLicenseUrlRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
|
||||||
|
@Override
|
||||||
|
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
|
||||||
|
DSpaceRestPermission restPermission) {
|
||||||
|
if (!StringUtils.equalsIgnoreCase(SubmissionCCLicenseUrlRest.NAME, targetType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -35,6 +35,7 @@ public interface AbstractRestProcessingStep extends ListenerProcessingStep {
|
|||||||
public static final String UPLOAD_STEP_MOVE_OPERATION_ENTRY = "bitstreammove";
|
public static final String UPLOAD_STEP_MOVE_OPERATION_ENTRY = "bitstreammove";
|
||||||
public static final String UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY = "accessConditions";
|
public static final String UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY = "accessConditions";
|
||||||
public static final String LICENSE_STEP_OPERATION_ENTRY = "granted";
|
public static final String LICENSE_STEP_OPERATION_ENTRY = "granted";
|
||||||
|
public static final String CCLICENSE_STEP_OPERATION_ENTRY = "cclicense/uri";
|
||||||
|
|
||||||
public static final String UPLOAD_STEP_METADATA_PATH = "metadata";
|
public static final String UPLOAD_STEP_METADATA_PATH = "metadata";
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ public interface AbstractRestProcessingStep extends ListenerProcessingStep {
|
|||||||
* the json patch operation
|
* the json patch operation
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||||
throws Exception;
|
SubmissionStepConfig stepConf) throws Exception;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import org.dspace.app.rest.model.CheckSumRest;
|
|||||||
import org.dspace.app.rest.model.MetadataValueRest;
|
import org.dspace.app.rest.model.MetadataValueRest;
|
||||||
import org.dspace.app.rest.model.UploadBitstreamAccessConditionDTO;
|
import org.dspace.app.rest.model.UploadBitstreamAccessConditionDTO;
|
||||||
import org.dspace.app.rest.model.WorkspaceItemRest;
|
import org.dspace.app.rest.model.WorkspaceItemRest;
|
||||||
|
import org.dspace.app.rest.model.step.DataCCLicense;
|
||||||
import org.dspace.app.rest.model.step.DataUpload;
|
import org.dspace.app.rest.model.step.DataUpload;
|
||||||
import org.dspace.app.rest.model.step.UploadBitstreamRest;
|
import org.dspace.app.rest.model.step.UploadBitstreamRest;
|
||||||
import org.dspace.app.rest.projection.Projection;
|
import org.dspace.app.rest.projection.Projection;
|
||||||
@@ -33,6 +34,8 @@ import org.dspace.authorize.AuthorizeException;
|
|||||||
import org.dspace.authorize.ResourcePolicy;
|
import org.dspace.authorize.ResourcePolicy;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.InProgressSubmission;
|
||||||
|
import org.dspace.content.Item;
|
||||||
import org.dspace.content.MetadataValue;
|
import org.dspace.content.MetadataValue;
|
||||||
import org.dspace.content.WorkspaceItem;
|
import org.dspace.content.WorkspaceItem;
|
||||||
import org.dspace.content.service.CollectionService;
|
import org.dspace.content.service.CollectionService;
|
||||||
@@ -41,6 +44,7 @@ import org.dspace.content.service.WorkspaceItemService;
|
|||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.Utils;
|
import org.dspace.core.Utils;
|
||||||
|
import org.dspace.license.service.CreativeCommonsService;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.dspace.services.RequestService;
|
import org.dspace.services.RequestService;
|
||||||
import org.dspace.services.model.Request;
|
import org.dspace.services.model.Request;
|
||||||
@@ -75,6 +79,8 @@ public class SubmissionService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected WorkflowService<XmlWorkflowItem> workflowService;
|
protected WorkflowService<XmlWorkflowItem> workflowService;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
protected CreativeCommonsService creativeCommonsService;
|
||||||
|
@Autowired
|
||||||
private RequestService requestService;
|
private RequestService requestService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConverterService converter;
|
private ConverterService converter;
|
||||||
@@ -136,19 +142,19 @@ public class SubmissionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the rest representation of a bitstream as used in the upload section
|
* Build the rest representation of a bitstream as used in the upload section
|
||||||
* ({@link DataUpload}. It contains all its metadata and the list of applied
|
* ({@link DataUpload}. It contains all its metadata and the list of applied
|
||||||
* access conditions (@link {@link UploadBitstreamAccessConditionDTO}
|
* access conditions (@link {@link UploadBitstreamAccessConditionDTO}
|
||||||
*
|
*
|
||||||
* @param configurationService the DSpace ConfigurationService
|
* @param configurationService the DSpace ConfigurationService
|
||||||
* @param source the bitstream to translate in its rest submission
|
* @param source the bitstream to translate in its rest submission
|
||||||
* representation
|
* representation
|
||||||
* @return
|
* @return
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public UploadBitstreamRest buildUploadBitstream(ConfigurationService configurationService, Bitstream source)
|
public UploadBitstreamRest buildUploadBitstream(ConfigurationService configurationService, Bitstream source)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
UploadBitstreamRest data = new UploadBitstreamRest();
|
UploadBitstreamRest data = new UploadBitstreamRest();
|
||||||
|
|
||||||
for (MetadataValue md : source.getMetadata()) {
|
for (MetadataValue md : source.getMetadata()) {
|
||||||
@@ -242,7 +248,7 @@ public class SubmissionService {
|
|||||||
wi = workflowService.start(context, wsi);
|
wi = workflowService.start(context, wsi);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("The workflow could not be started for workspaceItem with" +
|
throw new RuntimeException("The workflow could not be started for workspaceItem with" +
|
||||||
"id: " + id);
|
"id: " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wi;
|
return wi;
|
||||||
@@ -268,4 +274,27 @@ public class SubmissionService {
|
|||||||
public void saveWorkflowItem(Context context, XmlWorkflowItem source) throws SQLException, AuthorizeException {
|
public void saveWorkflowItem(Context context, XmlWorkflowItem source) throws SQLException, AuthorizeException {
|
||||||
workflowItemService.update(context, source);
|
workflowItemService.update(context, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the CC License data of an inprogress submission based on the cc license info present in the metadata
|
||||||
|
*
|
||||||
|
* @param obj - the in progress submission
|
||||||
|
* @return an object representing the CC License data
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws AuthorizeException
|
||||||
|
*/
|
||||||
|
public DataCCLicense getDataCCLicense(InProgressSubmission obj)
|
||||||
|
throws SQLException, IOException, AuthorizeException {
|
||||||
|
DataCCLicense result = new DataCCLicense();
|
||||||
|
Item item = obj.getItem();
|
||||||
|
|
||||||
|
result.setUri(creativeCommonsService.getLicenseURI(item));
|
||||||
|
result.setRights(creativeCommonsService.getLicenseName(item));
|
||||||
|
|
||||||
|
Bitstream licenseRdfBitstream = creativeCommonsService.getLicenseRdfBitstream(item);
|
||||||
|
result.setFile(converter.toRest(licenseRdfBitstream, Projection.DEFAULT));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.dspace.app.rest.model.MetadataValueRest;
|
import org.dspace.app.rest.model.MetadataValueRest;
|
||||||
import org.dspace.app.rest.model.patch.LateObjectEvaluator;
|
import org.dspace.app.rest.model.patch.LateObjectEvaluator;
|
||||||
|
import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.Bundle;
|
import org.dspace.content.Bundle;
|
||||||
import org.dspace.content.InProgressSubmission;
|
import org.dspace.content.InProgressSubmission;
|
||||||
@@ -39,12 +40,17 @@ public class BitstreamMetadataValueAddPatchOperation extends MetadataValueAddPat
|
|||||||
@Autowired
|
@Autowired
|
||||||
ItemService itemService;
|
ItemService itemService;
|
||||||
|
|
||||||
|
// this is wired in the pring-dspace-core-services.xml
|
||||||
|
BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void add(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
void add(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
//"path": "/sections/upload/files/0/metadata/dc.title/2"
|
//"path": "/sections/upload/files/0/metadata/dc.title/2"
|
||||||
//"abspath": "/files/0/metadata/dc.title/2"
|
//"abspath": "/files/0/metadata/dc.title/2"
|
||||||
String[] split = getAbsolutePath(path).split("/");
|
String absolutePath = getAbsolutePath(path);
|
||||||
|
String[] split = absolutePath.split("/");
|
||||||
|
bitstreamMetadataValuePathUtils.validate(absolutePath);
|
||||||
Item item = source.getItem();
|
Item item = source.getItem();
|
||||||
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
||||||
;
|
;
|
||||||
@@ -97,4 +103,8 @@ public class BitstreamMetadataValueAddPatchOperation extends MetadataValueAddPat
|
|||||||
protected BitstreamService getDSpaceObjectService() {
|
protected BitstreamService getDSpaceObjectService() {
|
||||||
return bitstreamService;
|
return bitstreamService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBitstreamMetadataValuePathUtils(BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils) {
|
||||||
|
this.bitstreamMetadataValuePathUtils = bitstreamMetadataValuePathUtils;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ package org.dspace.app.rest.submit.factory.impl;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.Bundle;
|
import org.dspace.content.Bundle;
|
||||||
import org.dspace.content.InProgressSubmission;
|
import org.dspace.content.InProgressSubmission;
|
||||||
@@ -35,12 +36,17 @@ public class BitstreamMetadataValueMovePatchOperation extends MetadataValueMoveP
|
|||||||
@Autowired
|
@Autowired
|
||||||
ItemService itemService;
|
ItemService itemService;
|
||||||
|
|
||||||
|
// this is wired in the pring-dspace-core-services.xml
|
||||||
|
BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void move(Context context, Request currentRequest, InProgressSubmission source, String path, String from)
|
void move(Context context, Request currentRequest, InProgressSubmission source, String path, String from)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
//"path": "/sections/upload/files/0/metadata/dc.title/2"
|
//"path": "/sections/upload/files/0/metadata/dc.title/2"
|
||||||
//"abspath": "/files/0/metadata/dc.title/2"
|
//"abspath": "/files/0/metadata/dc.title/2"
|
||||||
String[] splitTo = getAbsolutePath(path).split("/");
|
String absolutePath = getAbsolutePath(path);
|
||||||
|
String[] splitTo = absolutePath.split("/");
|
||||||
|
bitstreamMetadataValuePathUtils.validate(absolutePath);
|
||||||
Item item = source.getItem();
|
Item item = source.getItem();
|
||||||
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
||||||
for (Bundle bb : bundle) {
|
for (Bundle bb : bundle) {
|
||||||
@@ -72,4 +78,7 @@ public class BitstreamMetadataValueMovePatchOperation extends MetadataValueMoveP
|
|||||||
return bitstreamService;
|
return bitstreamService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBitstreamMetadataValuePathUtils(BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils) {
|
||||||
|
this.bitstreamMetadataValuePathUtils = bitstreamMetadataValuePathUtils;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ package org.dspace.app.rest.submit.factory.impl;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.Bundle;
|
import org.dspace.content.Bundle;
|
||||||
import org.dspace.content.InProgressSubmission;
|
import org.dspace.content.InProgressSubmission;
|
||||||
@@ -35,12 +36,17 @@ public class BitstreamMetadataValueRemovePatchOperation extends MetadataValueRem
|
|||||||
@Autowired
|
@Autowired
|
||||||
ItemService itemService;
|
ItemService itemService;
|
||||||
|
|
||||||
|
// this is wired in the pring-dspace-core-services.xml
|
||||||
|
BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void remove(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
void remove(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
//"path": "/sections/upload/files/0/metadata/dc.title/2"
|
//"path": "/sections/upload/files/0/metadata/dc.title/2"
|
||||||
//"abspath": "/files/0/metadata/dc.title/2"
|
//"abspath": "/files/0/metadata/dc.title/2"
|
||||||
String[] split = getAbsolutePath(path).split("/");
|
String absolutePath = getAbsolutePath(path);
|
||||||
|
String[] split = absolutePath.split("/");
|
||||||
|
bitstreamMetadataValuePathUtils.validate(absolutePath);
|
||||||
Item item = source.getItem();
|
Item item = source.getItem();
|
||||||
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
||||||
;
|
;
|
||||||
@@ -67,4 +73,7 @@ public class BitstreamMetadataValueRemovePatchOperation extends MetadataValueRem
|
|||||||
return bitstreamService;
|
return bitstreamService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBitstreamMetadataValuePathUtils(BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils) {
|
||||||
|
this.bitstreamMetadataValuePathUtils = bitstreamMetadataValuePathUtils;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.dspace.app.rest.model.MetadataValueRest;
|
import org.dspace.app.rest.model.MetadataValueRest;
|
||||||
import org.dspace.app.rest.model.patch.LateObjectEvaluator;
|
import org.dspace.app.rest.model.patch.LateObjectEvaluator;
|
||||||
|
import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.Bundle;
|
import org.dspace.content.Bundle;
|
||||||
import org.dspace.content.InProgressSubmission;
|
import org.dspace.content.InProgressSubmission;
|
||||||
@@ -38,12 +39,17 @@ public class BitstreamMetadataValueReplacePatchOperation extends MetadataValueRe
|
|||||||
@Autowired
|
@Autowired
|
||||||
ItemService itemService;
|
ItemService itemService;
|
||||||
|
|
||||||
|
// this is wired in the pring-dspace-core-services.xml
|
||||||
|
BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void replace(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
void replace(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
//"path": "/sections/upload/files/0/metadata/dc.title/2"
|
//"path": "/sections/upload/files/0/metadata/dc.title/2"
|
||||||
//"abspath": "/files/0/metadata/dc.title/2"
|
//"abspath": "/files/0/metadata/dc.title/2"
|
||||||
String[] split = getAbsolutePath(path).split("/");
|
String absolutePath = getAbsolutePath(path);
|
||||||
|
String[] split = absolutePath.split("/");
|
||||||
|
bitstreamMetadataValuePathUtils.validate(absolutePath);
|
||||||
Item item = source.getItem();
|
Item item = source.getItem();
|
||||||
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
||||||
for (Bundle bb : bundle) {
|
for (Bundle bb : bundle) {
|
||||||
@@ -80,4 +86,8 @@ public class BitstreamMetadataValueReplacePatchOperation extends MetadataValueRe
|
|||||||
protected BitstreamService getDSpaceObjectService() {
|
protected BitstreamService getDSpaceObjectService() {
|
||||||
return bitstreamService;
|
return bitstreamService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBitstreamMetadataValuePathUtils(BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils) {
|
||||||
|
this.bitstreamMetadataValuePathUtils = bitstreamMetadataValuePathUtils;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* 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.submit.factory.impl;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.content.InProgressSubmission;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.license.service.CreativeCommonsService;
|
||||||
|
import org.dspace.services.model.Request;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submission "add" PATCH operation
|
||||||
|
*
|
||||||
|
* To add or update the Creative Commons License of a workspace item.
|
||||||
|
* When the item already has a Creative Commons License, the license will be replaced with a new one.
|
||||||
|
*
|
||||||
|
* Example: <code>
|
||||||
|
* curl -X PATCH http://${dspace.server.url}/api/submission/workspaceitems/31599 -H "Content-Type:
|
||||||
|
* application/json" -d '[{ "op": "add", "path": "/sections/cclicense/uri",
|
||||||
|
* "value":"http://creativecommons.org/licenses/by-nc-sa/3.0/us/"}]'
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
public class CCLicenseAddPatchOperation extends AddPatchOperation<String> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
CreativeCommonsService creativeCommonsService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<String[]> getArrayClassForEvaluation() {
|
||||||
|
return String[].class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<String> getClassForEvaluation() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void add(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
|
||||||
|
String licenseUri = null;
|
||||||
|
if (value instanceof String) {
|
||||||
|
licenseUri = (String) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(licenseUri)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Value is not a valid license URI");
|
||||||
|
}
|
||||||
|
|
||||||
|
Item item = source.getItem();
|
||||||
|
boolean updateLicense = creativeCommonsService.updateLicense(context, licenseUri, item);
|
||||||
|
if (!updateLicense) {
|
||||||
|
throw new IllegalArgumentException("The license uri: " + licenseUri + ", could not be resolved to a " +
|
||||||
|
"CC license");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 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.submit.factory.impl;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.content.InProgressSubmission;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.license.service.CreativeCommonsService;
|
||||||
|
import org.dspace.services.model.Request;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submission "remove" PATCH operation
|
||||||
|
*
|
||||||
|
* To remove the Creative Commons License of a workspace item.
|
||||||
|
*
|
||||||
|
* Example: <code>
|
||||||
|
* curl -X PATCH http://${dspace.server.url}/api/submission/workspaceitems/31599 -H "Content-Type:
|
||||||
|
* application/json" -d '[{ "op": "remove", "path": "/sections/cclicense/uri"}]'
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
public class CCLicenseRemovePatchOperation extends RemovePatchOperation<String> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
CreativeCommonsService creativeCommonsService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<String[]> getArrayClassForEvaluation() {
|
||||||
|
return String[].class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<String> getClassForEvaluation() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void remove(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
||||||
|
throws Exception {
|
||||||
|
Item item = source.getItem();
|
||||||
|
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(creativeCommonsService.getLicenseName(item))) {
|
||||||
|
creativeCommonsService.removeLicense(context, item);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("No CC license can be removed since none is present on submission: "
|
||||||
|
+ source.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.submit.step;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
|
import org.dspace.app.rest.model.step.DataCCLicense;
|
||||||
|
import org.dspace.app.rest.submit.AbstractRestProcessingStep;
|
||||||
|
import org.dspace.app.rest.submit.SubmissionService;
|
||||||
|
import org.dspace.app.rest.submit.factory.PatchOperationFactory;
|
||||||
|
import org.dspace.app.rest.submit.factory.impl.PatchOperation;
|
||||||
|
import org.dspace.app.util.SubmissionStepConfig;
|
||||||
|
import org.dspace.content.InProgressSubmission;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.services.model.Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CC License step for DSpace Spring Rest. Expose the creative commons license information about the in progress
|
||||||
|
* submission.
|
||||||
|
*/
|
||||||
|
public class CCLicenseStep extends org.dspace.submit.step.CCLicenseStep implements AbstractRestProcessingStep {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the CC License data of the in progress submission
|
||||||
|
*
|
||||||
|
* @param submissionService the submission service
|
||||||
|
* @param obj the in progress submission
|
||||||
|
* @param config the submission step configuration
|
||||||
|
* @return the CC License data of the in progress submission
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DataCCLicense getData(SubmissionService submissionService, InProgressSubmission obj,
|
||||||
|
SubmissionStepConfig config)
|
||||||
|
throws Exception {
|
||||||
|
return submissionService.getDataCCLicense(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a patch for the CC License data
|
||||||
|
*
|
||||||
|
* @param context the DSpace context
|
||||||
|
* @param currentRequest the http request
|
||||||
|
* @param source the in progress submission
|
||||||
|
* @param op the json patch operation
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||||
|
SubmissionStepConfig stepConf) throws Exception {
|
||||||
|
|
||||||
|
if (op.getPath().endsWith(CCLICENSE_STEP_OPERATION_ENTRY)) {
|
||||||
|
|
||||||
|
PatchOperation<String> patchOperation = new PatchOperationFactory()
|
||||||
|
.instanceOf(CCLICENSE_STEP_OPERATION_ENTRY, op.getOp());
|
||||||
|
patchOperation.perform(context, currentRequest, source, op);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -36,8 +36,8 @@ public class CollectionStep extends org.dspace.submit.step.SelectCollectionStep
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||||
throws Exception {
|
SubmissionStepConfig stepConf) throws Exception {
|
||||||
|
|
||||||
PatchOperation<String> patchOperation = new PatchOperationFactory()
|
PatchOperation<String> patchOperation = new PatchOperationFactory()
|
||||||
.instanceOf(COLLECTION_STEP_OPERATION_ENTRY, op.getOp());
|
.instanceOf(COLLECTION_STEP_OPERATION_ENTRY, op.getOp());
|
||||||
|
@@ -10,9 +10,12 @@ package org.dspace.app.rest.submit.step;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||||
import org.dspace.app.rest.model.MetadataValueRest;
|
import org.dspace.app.rest.model.MetadataValueRest;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
|
import org.dspace.app.rest.model.patch.RemoveOperation;
|
||||||
import org.dspace.app.rest.model.step.DataDescribe;
|
import org.dspace.app.rest.model.step.DataDescribe;
|
||||||
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;
|
||||||
@@ -110,13 +113,56 @@ public class DescribeStep extends org.dspace.submit.step.DescribeStep implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||||
throws Exception {
|
SubmissionStepConfig stepConf) throws Exception {
|
||||||
|
|
||||||
PatchOperation<MetadataValueRest> patchOperation = new PatchOperationFactory()
|
|
||||||
.instanceOf(DESCRIBE_STEP_METADATA_OPERATION_ENTRY, op.getOp());
|
|
||||||
patchOperation.perform(context, currentRequest, source, op);
|
|
||||||
|
|
||||||
|
String[] pathParts = op.getPath().substring(1).split("/");
|
||||||
|
DCInputSet inputConfig = inputReader.getInputsByFormName(stepConf.getId());
|
||||||
|
if ("remove".equals(op.getOp()) && pathParts.length < 3) {
|
||||||
|
// manage delete all step fields
|
||||||
|
String[] path = op.getPath().substring(1).split("/", 3);
|
||||||
|
String configId = path[1];
|
||||||
|
List<String> fieldsName = getInputFieldsName(inputConfig, configId);
|
||||||
|
for (String fieldName : fieldsName) {
|
||||||
|
String fieldPath = op.getPath() + "/" + fieldName;
|
||||||
|
Operation fieldRemoveOp = new RemoveOperation(fieldPath);
|
||||||
|
PatchOperation<MetadataValueRest> patchOperation = new PatchOperationFactory()
|
||||||
|
.instanceOf(DESCRIBE_STEP_METADATA_OPERATION_ENTRY, fieldRemoveOp.getOp());
|
||||||
|
patchOperation.perform(context, currentRequest, source, fieldRemoveOp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PatchOperation<MetadataValueRest> patchOperation = new PatchOperationFactory()
|
||||||
|
.instanceOf(DESCRIBE_STEP_METADATA_OPERATION_ENTRY, op.getOp());
|
||||||
|
String[] split = patchOperation.getAbsolutePath(op.getPath()).split("/");
|
||||||
|
if (inputConfig.isFieldPresent(split[0])) {
|
||||||
|
patchOperation.perform(context, currentRequest, source, op);
|
||||||
|
} else {
|
||||||
|
throw new UnprocessableEntityException("The field " + split[0] + " is not present in section "
|
||||||
|
+ inputConfig.getFormName());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<String> getInputFieldsName(DCInputSet inputConfig, String configId) throws DCInputsReaderException {
|
||||||
|
List<String> fieldsName = new ArrayList<String>();
|
||||||
|
for (DCInput[] row : inputConfig.getFields()) {
|
||||||
|
for (DCInput input : row) {
|
||||||
|
if (input.isQualdropValue()) {
|
||||||
|
for (Object qualifier : input.getPairs()) {
|
||||||
|
fieldsName.add(input.getFieldName() + "." + (String) qualifier);
|
||||||
|
}
|
||||||
|
} else if (StringUtils.equalsIgnoreCase(input.getInputType(), "group") ||
|
||||||
|
StringUtils.equalsIgnoreCase(input.getInputType(), "inline-group")) {
|
||||||
|
log.info("Called child form:" + configId + "-" +
|
||||||
|
Utils.standardize(input.getSchema(), input.getElement(), input.getQualifier(), "-"));
|
||||||
|
DCInputSet inputConfigChild = inputReader.getInputsByFormName(configId + "-" + Utils
|
||||||
|
.standardize(input.getSchema(), input.getElement(), input.getQualifier(), "-"));
|
||||||
|
fieldsName.addAll(getInputFieldsName(inputConfigChild, configId));
|
||||||
|
} else {
|
||||||
|
fieldsName.add(input.getFieldName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fieldsName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.app.rest.submit.step;
|
package org.dspace.app.rest.submit.step;
|
||||||
|
|
||||||
import org.atteo.evo.inflector.English;
|
import org.atteo.evo.inflector.English;
|
||||||
|
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||||
import org.dspace.app.rest.model.BitstreamRest;
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.app.rest.model.step.DataLicense;
|
import org.dspace.app.rest.model.step.DataLicense;
|
||||||
@@ -50,8 +51,8 @@ public class LicenseStep extends org.dspace.submit.step.LicenseStep implements A
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||||
throws Exception {
|
SubmissionStepConfig stepConf) throws Exception {
|
||||||
|
|
||||||
if (op.getPath().endsWith(LICENSE_STEP_OPERATION_ENTRY)) {
|
if (op.getPath().endsWith(LICENSE_STEP_OPERATION_ENTRY)) {
|
||||||
|
|
||||||
@@ -59,6 +60,8 @@ public class LicenseStep extends org.dspace.submit.step.LicenseStep implements A
|
|||||||
.instanceOf(LICENSE_STEP_OPERATION_ENTRY, op.getOp());
|
.instanceOf(LICENSE_STEP_OPERATION_ENTRY, op.getOp());
|
||||||
patchOperation.perform(context, currentRequest, source, op);
|
patchOperation.perform(context, currentRequest, source, op);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new UnprocessableEntityException("The path " + op.getPath() + " cannot be patched");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ import java.io.InputStream;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||||
import org.dspace.app.rest.model.ErrorRest;
|
import org.dspace.app.rest.model.ErrorRest;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.app.rest.model.step.DataUpload;
|
import org.dspace.app.rest.model.step.DataUpload;
|
||||||
@@ -45,6 +46,8 @@ public class UploadStep extends org.dspace.submit.step.UploadStep
|
|||||||
|
|
||||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(UploadStep.class);
|
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(UploadStep.class);
|
||||||
|
|
||||||
|
public static final String UPLOAD_STEP_METADATA_SECTION = "bitstream-metadata";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataUpload getData(SubmissionService submissionService, InProgressSubmission obj,
|
public DataUpload getData(SubmissionService submissionService, InProgressSubmission obj,
|
||||||
SubmissionStepConfig config) throws Exception {
|
SubmissionStepConfig config) throws Exception {
|
||||||
@@ -61,10 +64,10 @@ public class UploadStep extends org.dspace.submit.step.UploadStep
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||||
throws Exception {
|
SubmissionStepConfig stepConf) throws Exception {
|
||||||
|
|
||||||
String instance = "";
|
String instance = null;
|
||||||
if ("remove".equals(op.getOp())) {
|
if ("remove".equals(op.getOp())) {
|
||||||
if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) {
|
if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) {
|
||||||
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
|
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
|
||||||
@@ -82,13 +85,16 @@ public class UploadStep extends org.dspace.submit.step.UploadStep
|
|||||||
} else {
|
} else {
|
||||||
if (op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) {
|
if (op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) {
|
||||||
instance = UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY;
|
instance = UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY;
|
||||||
} else {
|
} else if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) {
|
||||||
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
|
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (instance == null) {
|
||||||
|
throw new UnprocessableEntityException("The path " + op.getPath() + " is not supported by the operation "
|
||||||
|
+ op.getOp());
|
||||||
|
}
|
||||||
PatchOperation<?> patchOperation = new PatchOperationFactory().instanceOf(instance, op.getOp());
|
PatchOperation<?> patchOperation = new PatchOperationFactory().instanceOf(instance, op.getOp());
|
||||||
patchOperation.perform(context, currentRequest, source, op);
|
patchOperation.perform(context, currentRequest, source, op);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.utils;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||||
|
import org.dspace.app.rest.submit.step.UploadStep;
|
||||||
|
import org.dspace.app.util.DCInputSet;
|
||||||
|
import org.dspace.app.util.DCInputsReader;
|
||||||
|
import org.dspace.app.util.DCInputsReaderException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils class offering methods to validate patch operations for bitstream metadata in the submission
|
||||||
|
*
|
||||||
|
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.it)
|
||||||
|
*/
|
||||||
|
public class BitstreamMetadataValuePathUtils {
|
||||||
|
|
||||||
|
private DCInputsReader inputReader;
|
||||||
|
|
||||||
|
BitstreamMetadataValuePathUtils() throws DCInputsReaderException {
|
||||||
|
inputReader = new DCInputsReader();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to verify that the path included in the patch operation is supported
|
||||||
|
* by the submission configuration of the upload section
|
||||||
|
*
|
||||||
|
* @param absolutePath the path in the json patch operation
|
||||||
|
* @throws DCInputsReaderException if an error occurs reading the
|
||||||
|
* submission configuration
|
||||||
|
* @throws UnprocessableEntityException if the path is invalid
|
||||||
|
*/
|
||||||
|
public void validate(String absolutePath) throws DCInputsReaderException {
|
||||||
|
String[] split = absolutePath.split("/");
|
||||||
|
DCInputSet inputConfig = inputReader.getInputsByFormName(UploadStep.UPLOAD_STEP_METADATA_SECTION);
|
||||||
|
// according to the rest contract the absolute path must be something like files/:idx/metadata/dc.title
|
||||||
|
if (split.length >= 4) {
|
||||||
|
if (!inputConfig.isFieldPresent(split[3])) {
|
||||||
|
throw new UnprocessableEntityException("The field " + split[3] + " is not present in section "
|
||||||
|
+ UploadStep.UPLOAD_STEP_METADATA_SECTION);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new UnprocessableEntityException("The path " + absolutePath + " cannot be patched ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -25,7 +25,9 @@
|
|||||||
</entry>
|
</entry>
|
||||||
<entry key="bitstreammetadata">
|
<entry key="bitstreammetadata">
|
||||||
<bean
|
<bean
|
||||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueMovePatchOperation"/>
|
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueMovePatchOperation">
|
||||||
|
<property name="bitstreamMetadataValuePathUtils" ref="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" />
|
||||||
|
</bean>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="bitstreammove">
|
<entry key="bitstreammove">
|
||||||
<bean
|
<bean
|
||||||
@@ -42,7 +44,9 @@
|
|||||||
</entry>
|
</entry>
|
||||||
<entry key="bitstreammetadata">
|
<entry key="bitstreammetadata">
|
||||||
<bean
|
<bean
|
||||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueAddPatchOperation"/>
|
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueAddPatchOperation">
|
||||||
|
<property name="bitstreamMetadataValuePathUtils" ref="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" />
|
||||||
|
</bean>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="granted">
|
<entry key="granted">
|
||||||
<bean
|
<bean
|
||||||
@@ -52,6 +56,10 @@
|
|||||||
<bean
|
<bean
|
||||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyAddPatchOperation"/>
|
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyAddPatchOperation"/>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="cclicense/uri">
|
||||||
|
<bean
|
||||||
|
class="org.dspace.app.rest.submit.factory.impl.CCLicenseAddPatchOperation"/>
|
||||||
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="remove">
|
<entry key="remove">
|
||||||
@@ -59,11 +67,13 @@
|
|||||||
<!-- WARNING do not change "key" it match with Java code (TODO dynamic discover from PATCH operation); -->
|
<!-- WARNING do not change "key" it match with Java code (TODO dynamic discover from PATCH operation); -->
|
||||||
<entry key="itemmetadata">
|
<entry key="itemmetadata">
|
||||||
<bean
|
<bean
|
||||||
class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueRemovePatchOperation"/>
|
class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueRemovePatchOperation" />
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="bitstreammetadata">
|
<entry key="bitstreammetadata">
|
||||||
<bean
|
<bean
|
||||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueRemovePatchOperation"/>
|
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueRemovePatchOperation">
|
||||||
|
<property name="bitstreamMetadataValuePathUtils" ref="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" />
|
||||||
|
</bean>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="granted">
|
<entry key="granted">
|
||||||
<bean
|
<bean
|
||||||
@@ -71,12 +81,16 @@
|
|||||||
</entry>
|
</entry>
|
||||||
<entry key="bitstreamremove">
|
<entry key="bitstreamremove">
|
||||||
<bean
|
<bean
|
||||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamRemovePatchOperation"/>
|
class="org.dspace.app.rest.submit.factory.impl.BitstreamRemovePatchOperation" />
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="accessConditions">
|
<entry key="accessConditions">
|
||||||
<bean
|
<bean
|
||||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyRemovePatchOperation"/>
|
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyRemovePatchOperation"/>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="cclicense/uri">
|
||||||
|
<bean
|
||||||
|
class="org.dspace.app.rest.submit.factory.impl.CCLicenseRemovePatchOperation"/>
|
||||||
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="replace">
|
<entry key="replace">
|
||||||
@@ -88,7 +102,9 @@
|
|||||||
</entry>
|
</entry>
|
||||||
<entry key="bitstreammetadata">
|
<entry key="bitstreammetadata">
|
||||||
<bean
|
<bean
|
||||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueReplacePatchOperation"/>
|
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueReplacePatchOperation">
|
||||||
|
<property name="bitstreamMetadataValuePathUtils" ref="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" />
|
||||||
|
</bean>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="granted">
|
<entry key="granted">
|
||||||
<bean
|
<bean
|
||||||
@@ -108,4 +124,5 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" class="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils"/>
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -0,0 +1,282 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!DOCTYPE item-submission SYSTEM "item-submission.dtd">
|
||||||
|
|
||||||
|
<!-- Configurable Submission configuration file -->
|
||||||
|
|
||||||
|
<!-- This XML configuration file allows you to configure the ordering -->
|
||||||
|
<!-- and number of the steps that occur in the Item Submission Process. -->
|
||||||
|
<item-submission>
|
||||||
|
|
||||||
|
<!-- The process-map maps collection handles to a particular Item -->
|
||||||
|
<!-- Submission Process. This requires that a collection's name be -->
|
||||||
|
<!-- unique, even within a community. DSpace does however ensure that each -->
|
||||||
|
<!-- collection's handle is unique. Process-map provides the means to -->
|
||||||
|
<!-- associate a unique collection name with an Item Submission process. -->
|
||||||
|
<!-- The process-map also provides the special handle "default" (which is -->
|
||||||
|
<!-- never a collection), here mapped to "traditional". Any collection -->
|
||||||
|
<!-- which does not appear in this map will be associated with the mapping -->
|
||||||
|
<!-- for handle "default". -->
|
||||||
|
<submission-map>
|
||||||
|
<name-map collection-handle="default" submission-name="traditional"/>
|
||||||
|
</submission-map>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- The 'step-definitions' allows you to define steps which you may wish -->
|
||||||
|
<!-- to "share" amongst multiple submission-item definitions. In order to -->
|
||||||
|
<!-- share the same step definition, you can refer to it by its unique id -->
|
||||||
|
<!-- defined in this section. EVERY 'step' in this section MUST have a -->
|
||||||
|
<!-- unique identifier in the 'id' attribute! -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Each <step> REQUIRES the following attributes (@) and properties: -->
|
||||||
|
<!-- @id - The unique identifier for this step -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- <processing-class> - The class which will process all information for -->
|
||||||
|
<!-- this step. The class must extend -->
|
||||||
|
<!-- 'org.dspace.submit.AbstractProcessingStep' -->
|
||||||
|
<!-- (or one of the org.dspace.submit.step.* classes) -->
|
||||||
|
<!-- This property should reference the full path of the class -->
|
||||||
|
<!-- (e.g. org.dspace.submit.step.MyCustomStep) -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- The following properties are OPTIONAL for each <step>: -->
|
||||||
|
<!-- <heading> - References the message key, from the -->
|
||||||
|
<!-- Messages.properties -->
|
||||||
|
<!-- -->
|
||||||
|
<step-definitions>
|
||||||
|
<!-- The "collection" step is a "special step" which is *REQUIRED* -->
|
||||||
|
<!-- In DSpace, all submitted items must be immediately assigned -->
|
||||||
|
<!-- to a collection. This step ensures that a collection is always selected. -->
|
||||||
|
<step id="collection">
|
||||||
|
<heading></heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.CollectionStep</processing-class>
|
||||||
|
<type>collection</type>
|
||||||
|
<scope visibility="hidden" visibilityOutside="hidden">submission</scope>
|
||||||
|
</step>
|
||||||
|
<step id="traditionalpageone" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="traditionalpagetwo" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.steptwo</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
|
||||||
|
<step id="peopleStep" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="projectStep" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="orgUnitStep" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="journalStep" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="journalVolumeStep" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="journalIssueStep" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
|
||||||
|
<step id="upload">
|
||||||
|
<heading>submit.progressbar.upload</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.UploadStep</processing-class>
|
||||||
|
<type>upload</type>
|
||||||
|
</step>
|
||||||
|
<step id="license">
|
||||||
|
<heading>submit.progressbar.license</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.LicenseStep</processing-class>
|
||||||
|
<type>license</type>
|
||||||
|
<scope visibilityOutside="read-only">submission</scope>
|
||||||
|
</step>
|
||||||
|
|
||||||
|
<!-- Step Upload Item with Embargo Features to enable this step, please
|
||||||
|
make sure to comment-out the previous step "UploadStep" <step id="upload-with-embargo">
|
||||||
|
<heading>submit.progressbar.upload</heading> <processing-class>org.dspace.submit.step.UploadWithEmbargoStep</processing-class>
|
||||||
|
<type>uploadWithEmbargo</type> </step> -->
|
||||||
|
|
||||||
|
|
||||||
|
<!--Step will be to select a Creative Commons License -->
|
||||||
|
<!-- Uncomment this step to allow the user to select a Creative Commons
|
||||||
|
license -->
|
||||||
|
<step id="cclicense"> <heading>submit.progressbar.CClicense</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.CCLicenseStep</processing-class>
|
||||||
|
<type>cclicense</type> </step>
|
||||||
|
|
||||||
|
<!--Step will be to Check for potential duplicate -->
|
||||||
|
<!-- <step id="detect-duplicate"> <heading>submit.progressbar.detect.duplicate</heading>
|
||||||
|
<processing-class>org.dspace.submit.step.DetectPotentialDuplicate</processing-class>
|
||||||
|
<type>duplicate</type> </step> -->
|
||||||
|
|
||||||
|
<!--Step will be to Verify/Review everything -->
|
||||||
|
<!-- <step id="verify"> <heading>submit.progressbar.verify</heading> <processing-class>org.dspace.submit.step.VerifyStep</processing-class>
|
||||||
|
<type>verify</type> </step> -->
|
||||||
|
|
||||||
|
<!-- Fake Steps to test parsing of all options -->
|
||||||
|
<!-- <step mandatory="false"> <heading>fake.submission.readonly</heading>
|
||||||
|
<processing-class>org.dspace.submit.step.SampleStep</processing-class> <type>sample</type>
|
||||||
|
<scope visibility="read-only">submission</scope> </step> <step mandatory="false">
|
||||||
|
<heading>fake.workflow.readonly</heading> <processing-class>org.dspace.submit.step.SampleStep</processing-class>
|
||||||
|
<type>sample</type> <scope visibility="read-only">workflow</scope> </step> -->
|
||||||
|
|
||||||
|
<!-- OpenAIRE submission steps/forms -->
|
||||||
|
<step id="openAIREProjectForm" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="openAIREPersonForm" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="openAIREOrganizationForm" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="openAIREPublicationPageoneForm" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
<step id="openAIREPublicationPagetwoForm" mandatory="true">
|
||||||
|
<heading>submit.progressbar.describe.stepone</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||||
|
<type>submission-form</type>
|
||||||
|
</step>
|
||||||
|
|
||||||
|
<!-- This is the Sample Step which utilizes the JSPSampleStep class -->
|
||||||
|
<step id="sample">
|
||||||
|
<heading>Sample</heading>
|
||||||
|
<processing-class>org.dspace.submit.step.SampleStep</processing-class>
|
||||||
|
<type>sample</type>
|
||||||
|
</step>
|
||||||
|
</step-definitions>
|
||||||
|
|
||||||
|
<!-- The submission-definitions map lays out the detailed definition of -->
|
||||||
|
<!-- all the Item Submission Processes (and the ordering of their steps). -->
|
||||||
|
<!-- Each separate "submission-process" has a unique name as an attribute, -->
|
||||||
|
<!-- which matches one of the names in the process-map. One named -->
|
||||||
|
<!-- "submit-process" has the name "traditional"; as this name suggests, -->
|
||||||
|
<!-- it is the default item submission process, which gets used when -->
|
||||||
|
<!-- the specified collection has no correspondingly named submit-process. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Each submit-process contains an ordered set of steps; each step -->
|
||||||
|
<!-- defines one "step" occurring during the process of submitting an -->
|
||||||
|
<!-- item. A step MUST be referenced by 'id' (it must -->
|
||||||
|
<!-- be defined in <step-definitions> above). -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- -->
|
||||||
|
<submission-definitions>
|
||||||
|
|
||||||
|
<!--This "traditional" process defines the DEFAULT item submission process -->
|
||||||
|
<submission-process name="traditional">
|
||||||
|
|
||||||
|
<!--Uncommment to display the SAMPLE step as your first step -->
|
||||||
|
<!--<step id="sample"/> -->
|
||||||
|
|
||||||
|
<step id="collection"/>
|
||||||
|
|
||||||
|
<!--Step will be to Describe the item. -->
|
||||||
|
<step id="traditionalpageone"/>
|
||||||
|
<step id="traditionalpagetwo"/>
|
||||||
|
|
||||||
|
<!--Step will be to Upload the item -->
|
||||||
|
<step id="upload"/>
|
||||||
|
<!-- <step id="upload-with-embargo"/> -->
|
||||||
|
<!-- <step id="detect-duplicate"/> -->
|
||||||
|
|
||||||
|
<step id="cclicense"/>
|
||||||
|
|
||||||
|
<!--Step will be to Sign off on the License -->
|
||||||
|
<step id="license"/>
|
||||||
|
<!-- <step id="creative-commons"/> -->
|
||||||
|
<!-- <step id="verify"/> -->
|
||||||
|
</submission-process>
|
||||||
|
|
||||||
|
<submission-process name="People">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="peopleStep"/>
|
||||||
|
<step id="upload"/>
|
||||||
|
<step id="license"/>
|
||||||
|
</submission-process>
|
||||||
|
|
||||||
|
<submission-process name="Project">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="projectStep"/>
|
||||||
|
<step id="upload"/>
|
||||||
|
<step id="license"/>
|
||||||
|
</submission-process>
|
||||||
|
|
||||||
|
<submission-process name="OrgUnit">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="orgUnitStep"/>
|
||||||
|
<step id="upload"/>
|
||||||
|
<step id="license"/>
|
||||||
|
</submission-process>
|
||||||
|
<submission-process name="Journals">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="journalStep"/>
|
||||||
|
<step id="upload"/>
|
||||||
|
<step id="license"/>
|
||||||
|
</submission-process>
|
||||||
|
<submission-process name="JournalVolumes">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="journalVolumeStep"/>
|
||||||
|
<step id="upload"/>
|
||||||
|
<step id="license"/>
|
||||||
|
</submission-process>
|
||||||
|
<submission-process name="JournalIssues">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="journalIssueStep"/>
|
||||||
|
<step id="upload"/>
|
||||||
|
<step id="license"/>
|
||||||
|
</submission-process>
|
||||||
|
|
||||||
|
<!-- OpenAIRE submission processes -->
|
||||||
|
<submission-process name="openAIREPublicationSubmission">
|
||||||
|
<step id="collection"/>
|
||||||
|
|
||||||
|
<!--Step will be to Describe the item. -->
|
||||||
|
<step id="openAIREPublicationPageoneForm"/>
|
||||||
|
<step id="openAIREPublicationPagetwoForm"/>
|
||||||
|
|
||||||
|
<!--Step will be to Upload the item -->
|
||||||
|
<!-- step id="upload-with-embargo"/-->
|
||||||
|
<step id="upload"/>
|
||||||
|
|
||||||
|
<!--Step will be to Sign off on the License -->
|
||||||
|
<step id="license"/>
|
||||||
|
</submission-process>
|
||||||
|
<submission-process name="openAIREPersonSubmission">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="openAIREPersonForm"/>
|
||||||
|
</submission-process>
|
||||||
|
<submission-process name="openAIREProjectSubmission">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="openAIREProjectForm"/>
|
||||||
|
</submission-process>
|
||||||
|
<submission-process name="openAIREOrganizationSubmission">
|
||||||
|
<step id="collection"/>
|
||||||
|
<step id="openAIREOrganizationForm"/>
|
||||||
|
</submission-process>
|
||||||
|
</submission-definitions>
|
||||||
|
|
||||||
|
</item-submission>
|
@@ -6,4 +6,5 @@
|
|||||||
|
|
||||||
<!-- Replace harvestCollectionService with a mocked service -->
|
<!-- Replace harvestCollectionService with a mocked service -->
|
||||||
<bean class="org.dspace.harvest.MockHarvestedCollectionServiceImpl" id="org.dspace.harvest.service.HarvestedCollectionService" primary="true"/>
|
<bean class="org.dspace.harvest.MockHarvestedCollectionServiceImpl" id="org.dspace.harvest.service.HarvestedCollectionService" primary="true"/>
|
||||||
|
<bean class="org.dspace.license.MockCCLicenseConnectorServiceImpl" id="org.dspace.license.CCLicenseConnectorService" primary="true"/>
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -33,13 +33,14 @@ import org.dspace.app.rest.matcher.BitstreamMatcher;
|
|||||||
import org.dspace.app.rest.matcher.HalMatcher;
|
import org.dspace.app.rest.matcher.HalMatcher;
|
||||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||||
import org.dspace.app.rest.test.MetadataPatchSuite;
|
import org.dspace.app.rest.test.MetadataPatchSuite;
|
||||||
|
import org.dspace.authorize.service.ResourcePolicyService;
|
||||||
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;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.content.service.BitstreamService;
|
import org.dspace.content.service.BitstreamService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.hamcrest.Matchers;
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -49,6 +50,9 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
|
|||||||
@Autowired
|
@Autowired
|
||||||
private BitstreamService bitstreamService;
|
private BitstreamService bitstreamService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResourcePolicyService resourcePolicyService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void findAllTest() throws Exception {
|
public void findAllTest() throws Exception {
|
||||||
//We turn off the authorization system in order to create the structure as defined below
|
//We turn off the authorization system in order to create the structure as defined below
|
||||||
@@ -99,99 +103,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
|
|||||||
|
|
||||||
String token = getAuthToken(admin.getEmail(), password);
|
String token = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
getClient(token).perform(get("/api/core/bitstreams/")
|
getClient(token).perform(get("/api/core/bitstreams/"))
|
||||||
.param("projection", "full"))
|
.andExpect(status().isMethodNotAllowed());
|
||||||
.andExpect(status().isOk())
|
|
||||||
.andExpect(content().contentType(contentType))
|
|
||||||
.andExpect(jsonPath("$._embedded.bitstreams", Matchers.containsInAnyOrder(
|
|
||||||
BitstreamMatcher.matchBitstreamEntry(bitstream),
|
|
||||||
BitstreamMatcher.matchBitstreamEntry(bitstream1)
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void findAllPaginationTest() throws Exception {
|
|
||||||
//We turn off the authorization system in order to create the structure as defined below
|
|
||||||
context.turnOffAuthorisationSystem();
|
|
||||||
|
|
||||||
//** GIVEN **
|
|
||||||
//1. A community-collection structure with one parent community with sub-community and one collection.
|
|
||||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
|
||||||
.withName("Parent Community")
|
|
||||||
.build();
|
|
||||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
|
||||||
.withName("Sub Community")
|
|
||||||
.build();
|
|
||||||
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
|
|
||||||
|
|
||||||
//2. One public items that is readable by Anonymous
|
|
||||||
Item publicItem1 = ItemBuilder.createItem(context, col1)
|
|
||||||
.withTitle("Test")
|
|
||||||
.withIssueDate("2010-10-17")
|
|
||||||
.withAuthor("Smith, Donald")
|
|
||||||
.withSubject("ExtraEntry")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
String bitstreamContent = "ThisIsSomeDummyText";
|
|
||||||
//Add a bitstream to an item
|
|
||||||
Bitstream bitstream = null;
|
|
||||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
|
||||||
bitstream = BitstreamBuilder.
|
|
||||||
createBitstream(context, publicItem1, is)
|
|
||||||
.withName("Bitstream")
|
|
||||||
.withDescription("descr")
|
|
||||||
.withMimeType("text/plain")
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Add a bitstream to an item
|
|
||||||
Bitstream bitstream1 = null;
|
|
||||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
|
||||||
bitstream1 = BitstreamBuilder.
|
|
||||||
createBitstream(context, publicItem1, is)
|
|
||||||
.withName("Bitstream1")
|
|
||||||
.withDescription("desscrip1")
|
|
||||||
.withMimeType("text/plain")
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
context.restoreAuthSystemState();
|
|
||||||
|
|
||||||
String token = getAuthToken(admin.getEmail(), password);
|
|
||||||
|
|
||||||
getClient(token).perform(get("/api/core/bitstreams/")
|
|
||||||
.param("size", "1")
|
|
||||||
.param("projection", "full"))
|
|
||||||
.andExpect(status().isOk())
|
|
||||||
.andExpect(content().contentType(contentType))
|
|
||||||
.andExpect(jsonPath("$._embedded.bitstreams", Matchers.contains(
|
|
||||||
BitstreamMatcher.matchBitstreamEntry(bitstream))
|
|
||||||
))
|
|
||||||
.andExpect(jsonPath("$._embedded.bitstreams", Matchers.not(
|
|
||||||
Matchers.contains(
|
|
||||||
BitstreamMatcher.matchBitstreamEntry(bitstream1))
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
getClient(token).perform(get("/api/core/bitstreams/")
|
|
||||||
.param("size", "1")
|
|
||||||
.param("page", "1")
|
|
||||||
.param("projection", "full"))
|
|
||||||
.andExpect(status().isOk())
|
|
||||||
.andExpect(content().contentType(contentType))
|
|
||||||
.andExpect(jsonPath("$._embedded.bitstreams", Matchers.contains(
|
|
||||||
BitstreamMatcher.matchBitstreamEntry(bitstream1)
|
|
||||||
)))
|
|
||||||
.andExpect(jsonPath("$._embedded.bitstreams", Matchers.not(
|
|
||||||
Matchers.contains(
|
|
||||||
BitstreamMatcher.matchBitstreamEntry(bitstream)
|
|
||||||
)
|
|
||||||
)));
|
|
||||||
|
|
||||||
getClient().perform(get("/api/core/bitstreams/"))
|
|
||||||
.andExpect(status().isUnauthorized());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO Re-enable test after https://jira.duraspace.org/browse/DS-3774 is fixed
|
//TODO Re-enable test after https://jira.duraspace.org/browse/DS-3774 is fixed
|
||||||
@@ -322,6 +235,352 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findOneBitstreamTest_EmbargoedBitstream_Anon() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// a public item with an embargoed bitstream
|
||||||
|
String bitstreamContent = "Embargoed!";
|
||||||
|
|
||||||
|
Item publicItem1;
|
||||||
|
Bitstream bitstream;
|
||||||
|
try (InputStream is = IOUtils.toInputStream(bitstreamContent, org.apache.commons.lang3.CharEncoding.UTF_8)) {
|
||||||
|
|
||||||
|
publicItem1 = ItemBuilder.createItem(context, col1)
|
||||||
|
.withTitle("Public item 1")
|
||||||
|
.withIssueDate("2017-10-17")
|
||||||
|
.withAuthor("Smith, Donald")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bitstream = BitstreamBuilder
|
||||||
|
.createBitstream(context, publicItem1, is)
|
||||||
|
.withName("Test Embargoed Bitstream")
|
||||||
|
.withDescription("This bitstream is embargoed")
|
||||||
|
.withMimeType("text/plain")
|
||||||
|
.withEmbargoPeriod("3 months")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
// Bitstream metadata should still be accessible by anonymous request
|
||||||
|
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$", BitstreamMatcher.matchProperties(bitstream)))
|
||||||
|
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()))
|
||||||
|
.andExpect(jsonPath("$", BitstreamMatcher.matchLinks(bitstream.getID())))
|
||||||
|
;
|
||||||
|
|
||||||
|
// Also accessible as embedded object by anonymous request
|
||||||
|
getClient().perform(get("/api/core/items/" + publicItem1.getID() + "?embed=bundles/bitstreams"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.bundles._embedded.bundles[0]._embedded.bitstreams._embedded" +
|
||||||
|
".bitstreams[0]", BitstreamMatcher.matchProperties(bitstream)))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findOneBitstreamTest_NoReadPolicyOnBitstream_Anon() throws Exception {
|
||||||
|
//We turn off the authorization system in order to create the structure as defined below
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
//** GIVEN **
|
||||||
|
//1. A community-collection structure with one parent community with sub-community and one collection.
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||||
|
.withName("Sub Community")
|
||||||
|
.build();
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
|
||||||
|
|
||||||
|
//2. One public items that is readable by Anonymous
|
||||||
|
Item publicItem1 = ItemBuilder.createItem(context, col1)
|
||||||
|
.withTitle("Test")
|
||||||
|
.withIssueDate("2010-10-17")
|
||||||
|
.withAuthor("Smith, Donald")
|
||||||
|
.withSubject("ExtraEntry")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String bitstreamContent = "ThisIsSomeDummyText";
|
||||||
|
|
||||||
|
//Add a bitstream to an item
|
||||||
|
Bitstream bitstream = null;
|
||||||
|
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||||
|
bitstream = BitstreamBuilder.
|
||||||
|
createBitstream(context, publicItem1, is)
|
||||||
|
.withName("Bitstream")
|
||||||
|
.withDescription("Description")
|
||||||
|
.withMimeType("text/plain")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all READ policies on bitstream
|
||||||
|
resourcePolicyService.removePolicies(context, bitstream, Constants.READ);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
// Bitstream metadata should still be accessible by anonymous request
|
||||||
|
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$", BitstreamMatcher.matchProperties(bitstream)))
|
||||||
|
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()))
|
||||||
|
.andExpect(jsonPath("$", BitstreamMatcher.matchLinks(bitstream.getID())))
|
||||||
|
;
|
||||||
|
|
||||||
|
// Also accessible as embedded object by anonymous request
|
||||||
|
getClient().perform(get("/api/core/items/" + publicItem1.getID() + "?embed=bundles/bitstreams"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.bundles._embedded.bundles[0]._embedded.bitstreams._embedded" +
|
||||||
|
".bitstreams[0]", BitstreamMatcher.matchProperties(bitstream)))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findOneBitstreamTest_EmbargoedBitstream_NoREADRightsOnBundle() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
context.setCurrentUser(eperson);
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// a public item with an embargoed bitstream
|
||||||
|
String bitstreamContent = "Embargoed!";
|
||||||
|
|
||||||
|
Item publicItem1;
|
||||||
|
Bitstream bitstream;
|
||||||
|
try (InputStream is = IOUtils.toInputStream(bitstreamContent, org.apache.commons.lang3.CharEncoding.UTF_8)) {
|
||||||
|
|
||||||
|
publicItem1 = ItemBuilder.createItem(context, col1)
|
||||||
|
.withTitle("Public item 1")
|
||||||
|
.withIssueDate("2017-10-17")
|
||||||
|
.withAuthor("Smith, Donald")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bitstream = BitstreamBuilder
|
||||||
|
.createBitstream(context, publicItem1, is)
|
||||||
|
.withName("Test Embargoed Bitstream")
|
||||||
|
.withDescription("This bitstream is embargoed")
|
||||||
|
.withMimeType("text/plain")
|
||||||
|
.withEmbargoPeriod("3 months")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove read policies on bundle of bitstream
|
||||||
|
resourcePolicyService.removePolicies(context, bitstream.getBundles().get(0), Constants.READ);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
// Bitstream metadata should not be accessible by anonymous request
|
||||||
|
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isUnauthorized())
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bitstream metadata should not be accessible by submitter
|
||||||
|
String submitterToken = getAuthToken(context.getCurrentUser().getEmail(), password);
|
||||||
|
getClient(submitterToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isForbidden())
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bitstream metadata should be accessible by admin
|
||||||
|
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(adminToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findOneBitstreamTest_EmbargoedBitstream_ePersonREADRightsOnBundle() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
context.setCurrentUser(eperson);
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// a public item with an embargoed bitstream
|
||||||
|
String bitstreamContent = "Embargoed!";
|
||||||
|
|
||||||
|
Item publicItem1;
|
||||||
|
Bitstream bitstream;
|
||||||
|
try (InputStream is = IOUtils.toInputStream(bitstreamContent, org.apache.commons.lang3.CharEncoding.UTF_8)) {
|
||||||
|
|
||||||
|
publicItem1 = ItemBuilder.createItem(context, col1)
|
||||||
|
.withTitle("Public item 1")
|
||||||
|
.withIssueDate("2017-10-17")
|
||||||
|
.withAuthor("Smith, Donald")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bitstream = BitstreamBuilder
|
||||||
|
.createBitstream(context, publicItem1, is)
|
||||||
|
.withName("Test Embargoed Bitstream")
|
||||||
|
.withDescription("This bitstream is embargoed")
|
||||||
|
.withMimeType("text/plain")
|
||||||
|
.withEmbargoPeriod("3 months")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace anon read policy on bundle of bitstream with ePerson READ policy
|
||||||
|
resourcePolicyService.removePolicies(context, bitstream.getBundles().get(0), Constants.READ);
|
||||||
|
ResourcePolicyBuilder.createResourcePolicy(context).withUser(eperson)
|
||||||
|
.withAction(Constants.READ)
|
||||||
|
.withDspaceObject(bitstream.getBundles().get(0)).build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
// Bitstream metadata should not be accessible by anonymous request
|
||||||
|
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isUnauthorized())
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bitstream metadata should be accessible by eperson
|
||||||
|
String submitterToken = getAuthToken(context.getCurrentUser().getEmail(), password);
|
||||||
|
getClient(submitterToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bitstream metadata should be accessible by admin
|
||||||
|
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(adminToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findOneBitstreamTest_EmbargoedBitstream_NoREADRightsOnItem() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
context.setCurrentUser(eperson);
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// a public item with an embargoed bitstream
|
||||||
|
String bitstreamContent = "Embargoed!";
|
||||||
|
|
||||||
|
Item publicItem1;
|
||||||
|
Bitstream bitstream;
|
||||||
|
try (InputStream is = IOUtils.toInputStream(bitstreamContent, org.apache.commons.lang3.CharEncoding.UTF_8)) {
|
||||||
|
|
||||||
|
publicItem1 = ItemBuilder.createItem(context, col1)
|
||||||
|
.withTitle("Public item 1")
|
||||||
|
.withIssueDate("2017-10-17")
|
||||||
|
.withAuthor("Smith, Donald")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bitstream = BitstreamBuilder
|
||||||
|
.createBitstream(context, publicItem1, is)
|
||||||
|
.withName("Test Embargoed Bitstream")
|
||||||
|
.withDescription("This bitstream is embargoed")
|
||||||
|
.withMimeType("text/plain")
|
||||||
|
.withEmbargoPeriod("3 months")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove read policies on item of bitstream
|
||||||
|
resourcePolicyService.removePolicies(context, publicItem1, Constants.READ);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
// Bitstream metadata should not be accessible by anonymous request
|
||||||
|
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isUnauthorized())
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bitstream metadata should not be accessible by submitter
|
||||||
|
String submitterToken = getAuthToken(context.getCurrentUser().getEmail(), password);
|
||||||
|
getClient(submitterToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isForbidden())
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bitstream metadata should be accessible by admin
|
||||||
|
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(adminToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findOneBitstreamTest_EmbargoedBitstream_ePersonREADRightsOnItem() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
context.setCurrentUser(eperson);
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// a public item with an embargoed bitstream
|
||||||
|
String bitstreamContent = "Embargoed!";
|
||||||
|
|
||||||
|
Item publicItem1;
|
||||||
|
Bitstream bitstream;
|
||||||
|
try (InputStream is = IOUtils.toInputStream(bitstreamContent, org.apache.commons.lang3.CharEncoding.UTF_8)) {
|
||||||
|
|
||||||
|
publicItem1 = ItemBuilder.createItem(context, col1)
|
||||||
|
.withTitle("Public item 1")
|
||||||
|
.withIssueDate("2017-10-17")
|
||||||
|
.withAuthor("Smith, Donald")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bitstream = BitstreamBuilder
|
||||||
|
.createBitstream(context, publicItem1, is)
|
||||||
|
.withName("Test Embargoed Bitstream")
|
||||||
|
.withDescription("This bitstream is embargoed")
|
||||||
|
.withMimeType("text/plain")
|
||||||
|
.withEmbargoPeriod("3 months")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace anon read policy on item of bitstream with ePerson READ policy
|
||||||
|
resourcePolicyService.removePolicies(context, publicItem1, Constants.READ);
|
||||||
|
ResourcePolicyBuilder.createResourcePolicy(context).withUser(eperson)
|
||||||
|
.withAction(Constants.READ)
|
||||||
|
.withDspaceObject(publicItem1).build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
// Bitstream metadata should not be accessible by anonymous request
|
||||||
|
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isUnauthorized())
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bitstream metadata should be accessible by eperson
|
||||||
|
String submitterToken = getAuthToken(context.getCurrentUser().getEmail(), password);
|
||||||
|
getClient(submitterToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bitstream metadata should be accessible by admin
|
||||||
|
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(adminToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void findOneBitstreamRelsTest() throws Exception {
|
public void findOneBitstreamRelsTest() throws Exception {
|
||||||
|
|
||||||
|
@@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest;
|
||||||
|
|
||||||
|
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||||
|
import static org.hamcrest.Matchers.allOf;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||||
|
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||||
|
import org.dspace.app.rest.builder.WorkspaceItemBuilder;
|
||||||
|
import org.dspace.app.rest.model.patch.AddOperation;
|
||||||
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
|
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.WorkspaceItem;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to test the methods from the CCLicenseAddPatchOperation
|
||||||
|
* Since the CC Licenses are obtained from the CC License API, a mock service has been implemented
|
||||||
|
* This mock service will return a fixed set of CC Licenses using a similar structure to the ones obtained from the
|
||||||
|
* CC License API.
|
||||||
|
* Refer to {@link org.dspace.license.MockCCLicenseConnectorServiceImpl} for more information
|
||||||
|
*/
|
||||||
|
public class CCLicenseAddPatchOperationIT extends AbstractControllerIntegrationTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void patchSubmissionCCLicense() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Community community = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community)
|
||||||
|
.withName("Collection")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Workspace Item")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
List<Operation> ops = new ArrayList<Operation>();
|
||||||
|
AddOperation addOperation = new AddOperation("/sections/cclicense/uri",
|
||||||
|
"http://creativecommons.org/licenses/by-nc-sa/4.0/");
|
||||||
|
|
||||||
|
ops.add(addOperation);
|
||||||
|
String patchBody = getPatchContent(ops);
|
||||||
|
|
||||||
|
|
||||||
|
getClient(adminToken).perform(patch("/api/submission/workspaceitems/" + workspaceItem.getID())
|
||||||
|
.content(patchBody)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.sections.cclicense", allOf(
|
||||||
|
hasJsonPath("$.uri", is("http://creativecommons.org/licenses/by-nc-sa/4.0/")),
|
||||||
|
hasJsonPath("$.rights",
|
||||||
|
is("Attribution-NonCommercial-ShareAlike 4.0 International")),
|
||||||
|
hasJsonPath("$.file.name", is("license_rdf"))
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void patchSubmissionCCLicenseInvalid() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Community community = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community)
|
||||||
|
.withName("Collection")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Workspace Item")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
|
||||||
|
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
|
||||||
|
List<Operation> ops = new ArrayList<Operation>();
|
||||||
|
AddOperation addOperation = new AddOperation("/sections/cclicense/uri", "invalid-license-uri");
|
||||||
|
|
||||||
|
ops.add(addOperation);
|
||||||
|
String patchBody = getPatchContent(ops);
|
||||||
|
|
||||||
|
|
||||||
|
getClient(adminToken).perform(patch("/api/submission/workspaceitems/" + workspaceItem.getID())
|
||||||
|
.content(patchBody)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||||
|
.andExpect(status().isInternalServerError());
|
||||||
|
|
||||||
|
getClient(adminToken).perform(get("/api/submission/workspaceitems/" + workspaceItem.getID())
|
||||||
|
.content(patchBody)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.sections", not(hasJsonPath("cclicense"))));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user