mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +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;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -27,6 +23,7 @@ import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.authority.AuthorityValue;
|
||||
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
|
||||
*
|
||||
* @param f The file to read from
|
||||
* @param inputStream the inputstream to read from
|
||||
* @param c The DSpace Context
|
||||
* @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
|
||||
init();
|
||||
|
||||
// Open the CSV file
|
||||
BufferedReader input = null;
|
||||
try {
|
||||
input = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
|
||||
input = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||
|
||||
// Read the heading line
|
||||
String head = input.readLine();
|
||||
@@ -623,21 +620,15 @@ public class DSpaceCSV implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the CSV file to the given filename
|
||||
*
|
||||
* @param filename The filename to save the CSV file to
|
||||
* @throws IOException Thrown if an error occurs when writing the file
|
||||
* Creates and returns an InputStream from the CSV Lines in this DSpaceCSV
|
||||
* @return The InputStream created from the CSVLines in this DSpaceCSV
|
||||
*/
|
||||
public final void save(String filename) throws IOException {
|
||||
// Save the file
|
||||
BufferedWriter out = new BufferedWriter(
|
||||
new OutputStreamWriter(
|
||||
new FileOutputStream(filename), "UTF-8"));
|
||||
public InputStream getInputStream() {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (String csvLine : getCSVLinesAsStringArray()) {
|
||||
out.write(csvLine + "\n");
|
||||
stringBuilder.append(csvLine + "\n");
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
return IOUtils.toInputStream(stringBuilder.toString(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -8,271 +8,84 @@
|
||||
package org.dspace.app.bulkedit;
|
||||
|
||||
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.PosixParser;
|
||||
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.content.service.MetadataDSpaceCsvExportService;
|
||||
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
|
||||
*
|
||||
* @author Stuart Lewis
|
||||
*/
|
||||
public class MetadataExport {
|
||||
/**
|
||||
* The items to export
|
||||
*/
|
||||
protected Iterator<Item> toExport;
|
||||
public class MetadataExport extends DSpaceRunnable<MetadataExportScriptConfiguration> {
|
||||
|
||||
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";
|
||||
|
||||
/**
|
||||
* Whether to export all metadata, or just normally edited metadata
|
||||
*/
|
||||
protected boolean exportAll;
|
||||
private MetadataDSpaceCsvExportService metadataDSpaceCsvExportService = new DSpace().getServiceManager()
|
||||
.getServicesByType(MetadataDSpaceCsvExportService.class).get(0);
|
||||
|
||||
protected MetadataExport() {
|
||||
itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
}
|
||||
private EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||
|
||||
/**
|
||||
* Set up a new metadata export
|
||||
*
|
||||
* @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();
|
||||
@Override
|
||||
public void internalRun() throws Exception {
|
||||
|
||||
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 to export the community
|
||||
this.toExport = buildFromCommunity(c, toExport, 0);
|
||||
this.exportAll = exportAll;
|
||||
this.context = c;
|
||||
} catch (SQLException sqle) {
|
||||
// Something went wrong...
|
||||
System.err.println("Error running exporter:");
|
||||
sqle.printStackTrace(System.err);
|
||||
System.exit(1);
|
||||
context.setCurrentUser(ePersonService.find(context, this.getEpersonIdentifier()));
|
||||
} catch (SQLException e) {
|
||||
handler.handleException(e);
|
||||
}
|
||||
DSpaceCSV dSpaceCSV = metadataDSpaceCsvExportService
|
||||
.handleExport(context, exportAllItems, exportAllMetadata, handle,
|
||||
handler);
|
||||
handler.writeFilestream(context, filename, dSpaceCSV.getInputStream(), EXPORT_CSV);
|
||||
context.restoreAuthSystemState();
|
||||
context.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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;
|
||||
@Override
|
||||
public MetadataExportScriptConfiguration getScriptConfiguration() {
|
||||
return new DSpace().getServiceManager().getServiceByName("metadata-export",
|
||||
MetadataExportScriptConfiguration.class);
|
||||
}
|
||||
|
||||
private Iterator<Item> addItemsToResult(Iterator<Item> result, Iterator<Item> items) {
|
||||
if (result == null) {
|
||||
result = items;
|
||||
} else {
|
||||
result = Iterators.concat(result, items);
|
||||
}
|
||||
@Override
|
||||
public void setup() throws ParseException {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
if (commandLine.hasOption('h')) {
|
||||
help = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check a filename is given
|
||||
if (!line.hasOption('f')) {
|
||||
System.err.println("Required parameter -f missing!");
|
||||
printHelp(options, 1);
|
||||
if (!commandLine.hasOption('f')) {
|
||||
throw new ParseException("Required parameter -f missing!");
|
||||
}
|
||||
String filename = line.getOptionValue('f');
|
||||
filename = commandLine.getOptionValue('f');
|
||||
|
||||
// Create a context
|
||||
Context c = new Context(Context.Mode.READ_ONLY);
|
||||
c.turnOffAuthorisationSystem();
|
||||
exportAllMetadata = commandLine.hasOption('a');
|
||||
|
||||
// The things we'll export
|
||||
Iterator<Item> toExport = null;
|
||||
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);
|
||||
}
|
||||
if (!commandLine.hasOption('i')) {
|
||||
exportAllItems = true;
|
||||
}
|
||||
|
||||
// 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();
|
||||
handle = commandLine.getOptionValue('i');
|
||||
}
|
||||
}
|
||||
|
@@ -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.log4j.Logger;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
import org.dspace.scripts.factory.ScriptServiceFactory;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
import org.dspace.scripts.handler.impl.CommandLineDSpaceRunnableHandler;
|
||||
import org.dspace.scripts.service.ScriptService;
|
||||
import org.dspace.servicemanager.DSpaceKernelImpl;
|
||||
import org.dspace.servicemanager.DSpaceKernelInit;
|
||||
import org.dspace.services.RequestService;
|
||||
@@ -44,7 +46,8 @@ public class ScriptLauncher {
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
private ScriptLauncher() { }
|
||||
private ScriptLauncher() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the DSpace script launcher
|
||||
@@ -54,7 +57,7 @@ public class ScriptLauncher {
|
||||
* @throws FileNotFoundException if file doesn't exist
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
throws FileNotFoundException, IOException {
|
||||
throws FileNotFoundException, IOException, IllegalAccessException, InstantiationException {
|
||||
// Initialise the service manager kernel
|
||||
try {
|
||||
kernelImpl = DSpaceKernelInit.getKernel(null);
|
||||
@@ -107,13 +110,18 @@ public class ScriptLauncher {
|
||||
* @param commandConfigs The Document
|
||||
* @param dSpaceRunnableHandler The DSpaceRunnableHandler for this execution
|
||||
* @param kernelImpl The relevant DSpaceKernelImpl
|
||||
* @return A 1 or 0 depending on whether the script failed or passed respectively
|
||||
* @return A 1 or 0 depending on whether the script failed or passed respectively
|
||||
*/
|
||||
public static int handleScript(String[] args, Document commandConfigs,
|
||||
DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||
DSpaceKernelImpl kernelImpl) {
|
||||
DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||
DSpaceKernelImpl kernelImpl) throws InstantiationException, IllegalAccessException {
|
||||
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) {
|
||||
status = executeScript(args, dSpaceRunnableHandler, script);
|
||||
} 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 dSpaceRunnableHandler The relevant DSpaceRunnableHandler
|
||||
* @param script The script to be executed
|
||||
* @return A 1 or 0 depending on whether the script failed or passed respectively
|
||||
* @return A 1 or 0 depending on whether the script failed or passed respectively
|
||||
*/
|
||||
private static int executeScript(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||
DSpaceRunnable script) {
|
||||
try {
|
||||
script.initialize(args, dSpaceRunnableHandler);
|
||||
script.initialize(args, dSpaceRunnableHandler, null);
|
||||
script.run();
|
||||
return 0;
|
||||
} catch (ParseException e) {
|
||||
|
@@ -10,6 +10,7 @@ package org.dspace.app.util;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dspace.core.Utils;
|
||||
/**
|
||||
* 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 j = 0; j < inputs[i].length; j++) {
|
||||
DCInput field = inputs[i][j];
|
||||
String fullName = field.getFieldName();
|
||||
if (fullName.equals(fieldName)) {
|
||||
return true;
|
||||
// If this is a "qualdrop_value" field, then the full field name is the field + dropdown qualifier
|
||||
if (field.getInputType().equals("qualdrop_value")) {
|
||||
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) {
|
||||
// If we get here, major versions must be EQUAL. Now, time to check our minor versions
|
||||
return GREATER_THAN;
|
||||
} else if (firstMinor < secondMinor) {
|
||||
return LESS_THAN;
|
||||
} else {
|
||||
// This is an impossible scenario.
|
||||
// This 'else' should never be triggered since we've checked for equality above already
|
||||
return EQUAL;
|
||||
return LESS_THAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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 org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.dspace.content.Collection;
|
||||
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.handle.factory.HandleServiceFactory;
|
||||
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
|
||||
*/
|
||||
public class IndexClient extends DSpaceRunnable {
|
||||
public class IndexClient extends DSpaceRunnable<IndexDiscoveryScriptConfiguration> {
|
||||
|
||||
private Context context;
|
||||
|
||||
@Autowired
|
||||
private IndexingService indexer;
|
||||
private IndexingService indexer = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServiceByName(IndexingService.class.getName(),
|
||||
IndexingService.class);
|
||||
|
||||
private IndexClientOptions indexClientOptions;
|
||||
|
||||
@@ -144,6 +144,12 @@ public class IndexClient extends DSpaceRunnable {
|
||||
handler.logInfo("Done with indexing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexDiscoveryScriptConfiguration getScriptConfiguration() {
|
||||
return new DSpace().getServiceManager().getServiceByName("index-discovery",
|
||||
IndexDiscoveryScriptConfiguration.class);
|
||||
}
|
||||
|
||||
public void setup() throws ParseException {
|
||||
try {
|
||||
context = new Context(Context.Mode.READ_ONLY);
|
||||
@@ -151,18 +157,8 @@ public class IndexClient extends DSpaceRunnable {
|
||||
} catch (Exception e) {
|
||||
throw new ParseException("Unable to create a new DSpace Context: " + e.getMessage());
|
||||
}
|
||||
|
||||
indexClientOptions = IndexClientOptions.getIndexClientOption(commandLine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for this class. This will ensure that the Options are created and set appropriately.
|
||||
*/
|
||||
private IndexClient() {
|
||||
Options options = IndexClientOptions.constructOptions();
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author wbossons
|
||||
*/
|
||||
@@ -15,17 +17,17 @@ public class CCLicense {
|
||||
|
||||
private String licenseName;
|
||||
private String licenseId;
|
||||
private int order = 0;
|
||||
private List<CCLicenseField> ccLicenseFieldList;
|
||||
|
||||
public CCLicense() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CCLicense(String licenseId, String licenseName, int order) {
|
||||
public CCLicense(String licenseId, String licenseName, List<CCLicenseField> ccLicenseFieldList) {
|
||||
super();
|
||||
this.licenseId = licenseId;
|
||||
this.licenseName = licenseName;
|
||||
this.order = order;
|
||||
this.ccLicenseFieldList = ccLicenseFieldList;
|
||||
}
|
||||
|
||||
public String getLicenseName() {
|
||||
@@ -44,13 +46,19 @@ public class CCLicense {
|
||||
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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper class for representation of a license field declaration.
|
||||
@@ -22,7 +21,7 @@ public class CCLicenseField {
|
||||
private String description = "";
|
||||
private String type = "";
|
||||
|
||||
private HashMap fieldEnum = null;
|
||||
private List<CCLicenseFieldEnum> fieldEnum = null;
|
||||
|
||||
/**
|
||||
* 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 label The label to use when generating the user interface.
|
||||
*/
|
||||
public CCLicenseField(String id, String label) {
|
||||
super();
|
||||
|
||||
this.fieldEnum = new HashMap();
|
||||
|
||||
public CCLicenseField(String id, String label, String description, List<CCLicenseFieldEnum> fieldEnum) {
|
||||
this.id = id;
|
||||
this.label = label;
|
||||
this.description = description;
|
||||
this.fieldEnum = fieldEnum;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,16 +87,12 @@ public class CCLicenseField {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns an instance implementing the Map interface;
|
||||
* the instance contains a mapping from identifiers to
|
||||
* labels for the enumeration values.
|
||||
* @see Map
|
||||
* Returns the list of enums of this field
|
||||
* @return the list of enums of this field
|
||||
*/
|
||||
public Map<String, String> getEnum() {
|
||||
return this.fieldEnum;
|
||||
public List<CCLicenseFieldEnum> getFieldEnum() {
|
||||
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.StringWriter;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
@@ -82,9 +85,18 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
||||
protected BundleService bundleService;
|
||||
@Autowired(required = true)
|
||||
protected ItemService itemService;
|
||||
@Autowired
|
||||
protected CCLicenseConnectorService ccLicenseConnectorService;
|
||||
|
||||
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() {
|
||||
|
||||
}
|
||||
@@ -101,10 +113,14 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
||||
System.setProperty("http.proxyPort", proxyPort);
|
||||
}
|
||||
|
||||
ccLicenses = new HashMap<>();
|
||||
defaultLanguage = configurationService.getProperty("cc.license.locale", "en");
|
||||
jurisdiction = configurationService.getProperty("cc.license.jurisdiction", "");
|
||||
|
||||
try {
|
||||
templates = TransformerFactory.newInstance().newTemplates(
|
||||
new StreamSource(CreativeCommonsServiceImpl.class
|
||||
.getResourceAsStream("CreativeCommons.xsl")));
|
||||
new StreamSource(CreativeCommonsServiceImpl.class
|
||||
.getResourceAsStream("CreativeCommons.xsl")));
|
||||
} catch (TransformerConfigurationException 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
|
||||
// If it does, remove it and create a new one.
|
||||
protected Bundle getCcBundle(Context context, Item item)
|
||||
throws SQLException, AuthorizeException, IOException {
|
||||
throws SQLException, AuthorizeException, IOException {
|
||||
List<Bundle> bundles = itemService.getBundles(item, CC_BUNDLE_NAME);
|
||||
|
||||
if ((bundles.size() > 0) && (bundles.get(0) != null)) {
|
||||
@@ -131,8 +142,8 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
||||
|
||||
@Override
|
||||
public void setLicenseRDF(Context context, Item item, String licenseRdf)
|
||||
throws SQLException, IOException,
|
||||
AuthorizeException {
|
||||
throws SQLException, IOException,
|
||||
AuthorizeException {
|
||||
Bundle bundle = getCcBundle(context, item);
|
||||
// set the format
|
||||
BitstreamFormat bs_rdf_format = bitstreamFormatService.findByShortDescription(context, "RDF XML");
|
||||
@@ -144,7 +155,7 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
||||
@Override
|
||||
public void setLicense(Context context, Item item,
|
||||
InputStream licenseStm, String mimeType)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
Bundle bundle = getCcBundle(context, item);
|
||||
|
||||
// set the format
|
||||
@@ -160,17 +171,26 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
||||
Bitstream bs = bitstreamService.create(context, bundle, licenseStm);
|
||||
bs.setSource(context, CC_BS_SOURCE);
|
||||
bs.setName(context, (mimeType != null &&
|
||||
(mimeType.equalsIgnoreCase("text/xml") ||
|
||||
mimeType.equalsIgnoreCase("text/rdf"))) ?
|
||||
BSN_LICENSE_RDF : BSN_LICENSE_TEXT);
|
||||
(mimeType.equalsIgnoreCase("text/xml") ||
|
||||
mimeType.equalsIgnoreCase("text/rdf"))) ?
|
||||
BSN_LICENSE_RDF : BSN_LICENSE_TEXT);
|
||||
bs.setFormat(context, bs_format);
|
||||
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
|
||||
public void removeLicense(Context context, Item item)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
public void removeLicenseFile(Context context, Item item)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
// remove CC license bundle if one exists
|
||||
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
|
||||
public Bitstream getLicenseRdfBitstream(Item item) throws SQLException,
|
||||
IOException, AuthorizeException {
|
||||
IOException, AuthorizeException {
|
||||
return getBitstream(item, BSN_LICENSE_RDF);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public Bitstream getLicenseTextBitstream(Item item) throws SQLException,
|
||||
IOException, AuthorizeException {
|
||||
IOException, AuthorizeException {
|
||||
return getBitstream(item, BSN_LICENSE_TEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
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)) {
|
||||
return licenseUri;
|
||||
return getLicenseURI(item);
|
||||
}
|
||||
|
||||
// JSPUI backward compatibility see https://jira.duraspace.org/browse/DS-2604
|
||||
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
|
||||
public String fetchLicenseRDF(Document license) {
|
||||
StringWriter result = new StringWriter();
|
||||
|
||||
try {
|
||||
templates.newTransformer().transform(
|
||||
new JDOMSource(license),
|
||||
new StreamResult(result)
|
||||
new JDOMSource(license),
|
||||
new StreamResult(result)
|
||||
);
|
||||
} catch (TransformerException 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,
|
||||
String bitstream_name, BitstreamFormat format, byte[] bytes)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||
Bitstream bs = bitstreamService.create(context, bundle, bais);
|
||||
|
||||
@@ -297,7 +325,7 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
||||
*/
|
||||
protected String getStringFromBitstream(Context context, Item item,
|
||||
String bitstream_name) throws SQLException, IOException,
|
||||
AuthorizeException {
|
||||
AuthorizeException {
|
||||
byte[] bytes = getBytesFromBitstream(context, item, bitstream_name);
|
||||
|
||||
if (bytes == null) {
|
||||
@@ -320,7 +348,7 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
||||
* to perform a particular action.
|
||||
*/
|
||||
protected Bitstream getBitstream(Item item, String bitstream_name)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
Bundle cc_bundle = null;
|
||||
|
||||
// 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)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
Bitstream bs = getBitstream(item, bitstream_name);
|
||||
|
||||
// no such bitstream
|
||||
@@ -361,26 +389,322 @@ public class CreativeCommonsServiceImpl implements CreativeCommonsService, Initi
|
||||
* Returns a metadata field handle for given field Id
|
||||
*/
|
||||
@Override
|
||||
public LicenseMetadataValue getCCField(String fieldId) {
|
||||
return new LicenseMetadataValue(configurationService.getProperty("cc.license." + fieldId));
|
||||
public String getCCField(String 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
|
||||
public void removeLicense(Context context, LicenseMetadataValue uriField,
|
||||
LicenseMetadataValue nameField, Item item)
|
||||
throws AuthorizeException, IOException, SQLException {
|
||||
public void removeLicense(Context context, Item item)
|
||||
throws AuthorizeException, IOException, SQLException {
|
||||
|
||||
String uriField = getCCField("uri");
|
||||
String nameField = getCCField("name");
|
||||
|
||||
String licenseUri = itemService.getMetadata(item, uriField);
|
||||
|
||||
// only remove any previous licenses
|
||||
String licenseUri = uriField.ccItemValue(item);
|
||||
if (licenseUri != null) {
|
||||
uriField.removeItemValue(context, item, licenseUri);
|
||||
removeLicenseField(context, item, uriField);
|
||||
if (configurationService.getBooleanProperty("cc.submit.setname")) {
|
||||
String licenseName = nameField.keyedItemValue(item, licenseUri);
|
||||
nameField.removeItemValue(context, item, licenseName);
|
||||
removeLicenseField(context, item, nameField);
|
||||
}
|
||||
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.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.license.LicenseMetadataValue;
|
||||
import org.dspace.license.CCLicense;
|
||||
import org.jdom.Document;
|
||||
|
||||
/**
|
||||
@@ -29,13 +31,6 @@ public interface CreativeCommonsService {
|
||||
|
||||
public static final String CC_BUNDLE_NAME = "CC-LICENSE";
|
||||
|
||||
/**
|
||||
* Simple accessor for enabling of CC
|
||||
*
|
||||
* @return is CC enabled?
|
||||
*/
|
||||
public boolean isEnabled();
|
||||
|
||||
/**
|
||||
* setLicenseRDF
|
||||
*
|
||||
@@ -50,7 +45,7 @@ public interface CreativeCommonsService {
|
||||
* to perform a particular action.
|
||||
*/
|
||||
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,
|
||||
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)
|
||||
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.
|
||||
@@ -97,7 +113,7 @@ public interface CreativeCommonsService {
|
||||
* to perform a particular action.
|
||||
*/
|
||||
public Bitstream getLicenseRdfBitstream(Item item)
|
||||
throws SQLException, IOException, AuthorizeException;
|
||||
throws SQLException, IOException, AuthorizeException;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
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
|
||||
@@ -121,7 +137,7 @@ public interface CreativeCommonsService {
|
||||
* @param fieldId name of the property.
|
||||
* @return its value.
|
||||
*/
|
||||
public LicenseMetadataValue getCCField(String fieldId);
|
||||
public String getCCField(String fieldId);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param context - DSpace Context
|
||||
* @param uriField - the metadata field for license uri
|
||||
* @param nameField - the metadata field for license name
|
||||
* @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.
|
||||
*/
|
||||
public void removeLicense(Context context, LicenseMetadataValue uriField,
|
||||
LicenseMetadataValue nameField, Item item)
|
||||
throws AuthorizeException, IOException, SQLException;
|
||||
public void removeLicense(Context context, Item item)
|
||||
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;
|
||||
|
||||
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.DefaultParser;
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.core.Context;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
/**
|
||||
* This abstract class is the class that should be extended by each script.
|
||||
* it provides the basic variables to be hold by the script as well as the means to initialize, parse and run the script
|
||||
* Every DSpaceRunnable that is implemented in this way should be defined in the scripts.xml config file as a bean
|
||||
* This is the class that should be extended for each Script. This class will contain the logic needed to run and it'll
|
||||
* fetch the information that it needs from the {@link ScriptConfiguration} provided through the diamond operators.
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
* a CommandlineDSpaceRunnableHandler depending from where the script is called
|
||||
*/
|
||||
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.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
/**
|
||||
* 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
|
||||
* @param currentUser
|
||||
* @throws ParseException If something goes wrong
|
||||
*/
|
||||
public void initialize(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler,
|
||||
EPerson currentUser) throws ParseException {
|
||||
if (currentUser != null) {
|
||||
this.setEpersonIdentifier(currentUser.getID());
|
||||
}
|
||||
this.setHandler(dSpaceRunnableHandler);
|
||||
this.parse(args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,18 +82,16 @@ public abstract class DSpaceRunnable implements Runnable {
|
||||
* @throws ParseException If something goes wrong
|
||||
*/
|
||||
private void parse(String[] args) throws ParseException {
|
||||
commandLine = new DefaultParser().parse(getOptions(), args);
|
||||
commandLine = new DefaultParser().parse(getScriptConfiguration().getOptions(), args);
|
||||
setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will call upon the {@link DSpaceRunnableHandler#printHelp(Options, String)} method with the script's
|
||||
* options and name
|
||||
* This method has to be included in every script and handles the setup of the script by parsing the CommandLine
|
||||
* and setting the variables
|
||||
* @throws ParseException If something goes wrong
|
||||
*/
|
||||
public void printHelp() {
|
||||
handler.printHelp(options, name);
|
||||
}
|
||||
|
||||
public abstract void setup() throws ParseException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* contain all the logic needed
|
||||
@@ -132,25 +116,46 @@ public abstract class DSpaceRunnable implements Runnable {
|
||||
public abstract void internalRun() throws Exception;
|
||||
|
||||
/**
|
||||
* This method has to be included in every script and handles the setup of the script by parsing the CommandLine
|
||||
* and setting the variables
|
||||
* @throws ParseException If something goes wrong
|
||||
* This method will call upon the {@link DSpaceRunnableHandler#printHelp(Options, String)} method with the script's
|
||||
* options and name
|
||||
*/
|
||||
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
|
||||
* 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
|
||||
* This method will traverse all the options and it'll grab options defined as an InputStream type to then save
|
||||
* the filename specified by that option in a list of Strings that'll be returned in the end
|
||||
* @return The list of Strings representing filenames from the options given to the script
|
||||
*/
|
||||
public boolean isAllowedToExecute(Context context) {
|
||||
try {
|
||||
return authorizeService.isAdmin(context);
|
||||
} catch (SQLException e) {
|
||||
handler.logError("Error occured when trying to verify permissions for script: " + name);
|
||||
public List<String> getFileNamesFromInputStreamOptions() {
|
||||
List<String> fileNames = new LinkedList<>();
|
||||
|
||||
for (Option option : getScriptConfiguration().getOptions().getOptions()) {
|
||||
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;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
@@ -80,6 +81,8 @@ public class Process implements ReloadableEntity<Integer> {
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date creationTime;
|
||||
|
||||
public static final String BITSTREAM_TYPE_METADATAFIELD = "dspace.process.filetype";
|
||||
|
||||
protected Process() {
|
||||
}
|
||||
|
||||
@@ -174,6 +177,9 @@ public class Process implements ReloadableEntity<Integer> {
|
||||
* @return The Bitstreams that are used or created by the process
|
||||
*/
|
||||
public List<Bitstream> getBitstreams() {
|
||||
if (bitstreams == null) {
|
||||
bitstreams = new LinkedList<>();
|
||||
}
|
||||
return bitstreams;
|
||||
}
|
||||
|
||||
|
@@ -7,18 +7,33 @@
|
||||
*/
|
||||
package org.dspace.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
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.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.LogManager;
|
||||
import org.dspace.eperson.EPerson;
|
||||
@@ -35,6 +50,18 @@ public class ProcessServiceImpl implements ProcessService {
|
||||
@Autowired
|
||||
private ProcessDAO processDAO;
|
||||
|
||||
@Autowired
|
||||
private BitstreamService bitstreamService;
|
||||
|
||||
@Autowired
|
||||
private BitstreamFormatService bitstreamFormatService;
|
||||
|
||||
@Autowired
|
||||
private AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
private MetadataFieldService metadataFieldService;
|
||||
|
||||
@Override
|
||||
public Process create(Context context, EPerson ePerson, String scriptName,
|
||||
List<DSpaceCommandLineParameter> parameters) throws SQLException {
|
||||
@@ -113,11 +140,35 @@ public class ProcessServiceImpl implements ProcessService {
|
||||
}
|
||||
|
||||
@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);
|
||||
log.info(LogManager.getHeader(context, "process_delete", "Process with ID " + process.getID()
|
||||
+ " and name " + process.getName() + " has been deleted"));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,8 +192,57 @@ public class ProcessServiceImpl implements ProcessService {
|
||||
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 {
|
||||
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;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.kernel.ServiceManager;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
import org.dspace.scripts.service.ScriptService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* The implementation for the {@link ScriptService}
|
||||
*/
|
||||
public class ScriptServiceImpl implements ScriptService {
|
||||
private static final Logger log = LoggerFactory.getLogger(ScriptServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private List<DSpaceRunnable> dSpaceRunnables;
|
||||
private ServiceManager serviceManager;
|
||||
|
||||
@Override
|
||||
public DSpaceRunnable getScriptForName(String name) {
|
||||
return dSpaceRunnables.stream()
|
||||
.filter(dSpaceRunnable -> StringUtils.equalsIgnoreCase(dSpaceRunnable.getName(), name))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
public ScriptConfiguration getScriptConfiguration(String name) {
|
||||
return serviceManager.getServiceByName(name, ScriptConfiguration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DSpaceRunnable> getDSpaceRunnables(Context context) {
|
||||
return dSpaceRunnables.stream().filter(
|
||||
dSpaceRunnable -> dSpaceRunnable.isAllowedToExecute(context)).collect(Collectors.toList());
|
||||
public List<ScriptConfiguration> getScriptConfigurations(Context context) {
|
||||
return serviceManager.getServicesByType(ScriptConfiguration.class).stream().filter(
|
||||
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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
|
||||
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
|
||||
@@ -78,4 +83,28 @@ public interface DSpaceRunnableHandler {
|
||||
* @param name The name of the script
|
||||
*/
|
||||
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;
|
||||
|
||||
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.Options;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
|
||||
/**
|
||||
@@ -84,4 +91,20 @@ public class CommandLineDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
||||
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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||
@@ -104,13 +108,28 @@ public interface ProcessService {
|
||||
*/
|
||||
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
|
||||
* @param context The relevant DSpace context
|
||||
* @param process The Process object to be deleted
|
||||
* @throws SQLException If something goes wrong
|
||||
*/
|
||||
public void delete(Context context, Process process) throws SQLException;
|
||||
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
|
||||
@@ -128,6 +147,32 @@ public interface ProcessService {
|
||||
*/
|
||||
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
|
||||
* @param context The relevant DSpace context
|
||||
@@ -136,4 +181,12 @@ public interface ProcessService {
|
||||
*/
|
||||
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.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
|
||||
/**
|
||||
* This service will deal with logic to handle DSpaceRunnable objects
|
||||
@@ -18,16 +19,29 @@ import org.dspace.scripts.DSpaceRunnable;
|
||||
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
|
||||
* @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
|
||||
* @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 -->
|
||||
<!-- Uncomment this step to allow the user to select a Creative Commons
|
||||
license -->
|
||||
<!-- <step id="creative-commons"> <heading>submit.progressbar.CClicense</heading>
|
||||
<processing-class>org.dspace.submit.step.CCLicenseStep</processing-class>
|
||||
<type>cclicense</type> </step> -->
|
||||
<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>
|
||||
@@ -145,7 +145,7 @@
|
||||
|
||||
<!--Step will be to Sign off on the License -->
|
||||
<step id="license"/>
|
||||
<!-- <step id="creative-commons"/> -->
|
||||
<step id="cclicense"/>
|
||||
<!-- <step id="verify"/> -->
|
||||
</submission-process>
|
||||
|
||||
|
@@ -4,13 +4,23 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||
|
||||
<bean id="indexClient" class="org.dspace.discovery.IndexClient" scope="prototype">
|
||||
<property name="name" value="index-discovery"/>
|
||||
<bean id="index-discovery" class="org.dspace.discovery.IndexDiscoveryScriptConfiguration">
|
||||
<property name="description" value="Update Discovery Solr Search Index"/>
|
||||
<property name="dspaceRunnableClass" value="org.dspace.discovery.IndexClient"/>
|
||||
</bean>
|
||||
|
||||
<bean id="MockScript" class="org.dspace.scripts.impl.MockDSpaceRunnableScript" scope="prototype">
|
||||
<property name="name" value="mock-script" />
|
||||
<bean id="metadata-import" class="org.dspace.app.bulkedit.MetadataImportCliScriptConfiguration">
|
||||
<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="dspaceRunnableClass" value="org.dspace.scripts.impl.MockDSpaceRunnableScript"/>
|
||||
</bean>
|
||||
</beans>
|
||||
|
@@ -18,6 +18,7 @@ import java.io.OutputStreamWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.AbstractUnitTest;
|
||||
import org.junit.Test;
|
||||
@@ -67,7 +68,7 @@ public class DSpaceCSVTest extends AbstractUnitTest {
|
||||
out = null;
|
||||
|
||||
// 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();
|
||||
assertThat("testDSpaceCSV Good CSV", lines.length, equalTo(8));
|
||||
|
||||
@@ -96,7 +97,7 @@ public class DSpaceCSVTest extends AbstractUnitTest {
|
||||
|
||||
// Test the CSV parsing was OK
|
||||
try {
|
||||
dcsv = new DSpaceCSV(new File(filename), context);
|
||||
dcsv = new DSpaceCSV(FileUtils.openInputStream(new File(filename)), context);
|
||||
lines = dcsv.getCSVLinesAsStringArray();
|
||||
|
||||
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
|
||||
try {
|
||||
dcsv = new DSpaceCSV(new File(filename), context);
|
||||
dcsv = new DSpaceCSV(FileUtils.openInputStream(new File(filename)), context);
|
||||
lines = dcsv.getCSVLinesAsStringArray();
|
||||
|
||||
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;
|
||||
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.MockDSpaceRunnableScriptConfiguration;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
public class MockDSpaceRunnableScript extends DSpaceRunnable {
|
||||
|
||||
private MockDSpaceRunnableScript() {
|
||||
Options options = constructOptions();
|
||||
this.options = options;
|
||||
public class MockDSpaceRunnableScript extends DSpaceRunnable<MockDSpaceRunnableScriptConfiguration> {
|
||||
@Override
|
||||
public void internalRun() throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalRun() throws Exception {
|
||||
public MockDSpaceRunnableScriptConfiguration getScriptConfiguration() {
|
||||
return new DSpace().getServiceManager()
|
||||
.getServiceByName("mock-script", MockDSpaceRunnableScriptConfiguration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -28,15 +29,4 @@ public class MockDSpaceRunnableScript extends DSpaceRunnable {
|
||||
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)
|
||||
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);
|
||||
|
||||
items = new ArrayList<Item>();
|
||||
Iterator<org.dspace.content.Item> dspaceItems = itemService.findByCollection(context, dspaceCollection);
|
||||
for (int i = 0; (dspaceItems.hasNext()) && (i < (limit + offset)); i++) {
|
||||
Iterator<org.dspace.content.Item> dspaceItems = itemService.findByCollection(context, dspaceCollection,
|
||||
limit, offset);
|
||||
|
||||
while (dspaceItems.hasNext()) {
|
||||
org.dspace.content.Item dspaceItem = dspaceItems.next();
|
||||
|
||||
if (i >= offset) {
|
||||
if (itemService.isItemListedForUser(context, dspaceItem)) {
|
||||
items.add(new Item(dspaceItem, servletContext, expand, context));
|
||||
writeStats(dspaceItem, UsageEvent.Action.VIEW, user_ip, user_agent, xforwardedfor,
|
||||
headers, request, context);
|
||||
}
|
||||
if (itemService.isItemListedForUser(context, dspaceItem)) {
|
||||
items.add(new Item(dspaceItem, servletContext, expand, context));
|
||||
writeStats(dspaceItem, UsageEvent.Action.VIEW, user_ip, user_agent, xforwardedfor,
|
||||
headers, request, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -342,7 +342,15 @@ public class RestResourceController implements InitializingBean {
|
||||
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;
|
||||
*
|
||||
|
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* This controller adds additional subresource methods to allow connecting scripts with processes
|
||||
@@ -56,13 +60,14 @@ public class ScriptProcessesController {
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@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 {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Starting Process for Script with name: " + scriptName);
|
||||
}
|
||||
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);
|
||||
context.complete();
|
||||
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.ScriptRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -23,18 +23,18 @@ import org.springframework.stereotype.Component;
|
||||
* of {@link ScriptRest}
|
||||
*/
|
||||
@Component
|
||||
public class ScriptConverter implements DSpaceConverter<DSpaceRunnable, ScriptRest> {
|
||||
public class ScriptConverter implements DSpaceConverter<ScriptConfiguration, ScriptRest> {
|
||||
|
||||
@Override
|
||||
public ScriptRest convert(DSpaceRunnable script, Projection projection) {
|
||||
public ScriptRest convert(ScriptConfiguration scriptConfiguration, Projection projection) {
|
||||
ScriptRest scriptRest = new ScriptRest();
|
||||
scriptRest.setProjection(projection);
|
||||
scriptRest.setDescription(script.getDescription());
|
||||
scriptRest.setId(script.getName());
|
||||
scriptRest.setName(script.getName());
|
||||
scriptRest.setDescription(scriptConfiguration.getDescription());
|
||||
scriptRest.setId(scriptConfiguration.getName());
|
||||
scriptRest.setName(scriptConfiguration.getName());
|
||||
|
||||
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.setDescription(option.getDescription());
|
||||
parameterRest.setName((option.getOpt() != null ? "-" + option.getOpt() : "--" + option.getLongOpt()));
|
||||
@@ -49,7 +49,7 @@ public class ScriptConverter implements DSpaceConverter<DSpaceRunnable, ScriptRe
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<DSpaceRunnable> getModelClass() {
|
||||
return DSpaceRunnable.class;
|
||||
public Class<ScriptConfiguration> getModelClass() {
|
||||
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.ResponseStatus;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
|
||||
/**
|
||||
@@ -54,8 +55,8 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
|
||||
}
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
protected void handleIllegalArgumentException(HttpServletRequest request, HttpServletResponse response,
|
||||
@ExceptionHandler({IllegalArgumentException.class, MultipartException.class})
|
||||
protected void handleWrongRequestException(HttpServletRequest request, HttpServletResponse response,
|
||||
Exception ex) throws IOException {
|
||||
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 org.dspace.app.rest.RestResourceController;
|
||||
import org.dspace.app.rest.link.HalLinkFactory;
|
||||
import org.dspace.app.rest.model.hateoas.ProcessResource;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -19,14 +18,15 @@ import org.springframework.hateoas.Link;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This class will provide the ProcessResource with links
|
||||
* This HalLinkFactory provides the {@link ProcessResource} with links
|
||||
*/
|
||||
@Component
|
||||
public class ProcessResourceHalLinkFactory extends HalLinkFactory<ProcessResource, RestResourceController> {
|
||||
public class ProcessResourceHalLinkFactory extends ProcessHalLinkFactory<ProcessResource> {
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Override
|
||||
protected void addLinks(ProcessResource halResource, Pageable pageable, LinkedList<Link> list) throws Exception {
|
||||
String dspaceServerUrl = configurationService.getProperty("dspace.server.url");
|
||||
list.add(
|
||||
@@ -34,10 +34,12 @@ public class ProcessResourceHalLinkFactory extends HalLinkFactory<ProcessResourc
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<RestResourceController> getControllerClass() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ProcessResource> getResourceClass() {
|
||||
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;
|
||||
|
||||
/**
|
||||
* The long name of the parameter
|
||||
*/
|
||||
private String nameLong;
|
||||
|
||||
/**
|
||||
* Boolean indicating whether the parameter is mandatory or not
|
||||
*/
|
||||
private boolean mandatory;
|
||||
|
||||
/**
|
||||
* The long name of the parameter
|
||||
*/
|
||||
private String nameLong;
|
||||
|
||||
public String getName() {
|
||||
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
|
||||
*/
|
||||
@LinksRest(links = {
|
||||
@LinkRest(
|
||||
name = ProcessRest.FILES,
|
||||
method = "getFilesFromProcess"
|
||||
),
|
||||
@LinkRest(
|
||||
name = ProcessRest.FILE_TYPES,
|
||||
method = "getFileTypesFromProcess"
|
||||
)
|
||||
})
|
||||
public class ProcessRest extends BaseObjectRest<Integer> {
|
||||
public static final String NAME = "process";
|
||||
public static final String PLURAL_NAME = "processes";
|
||||
public static final String CATEGORY = RestAddressableModel.SYSTEM;
|
||||
|
||||
|
||||
public static final String FILES = "files";
|
||||
public static final String FILE_TYPES = "filetypes";
|
||||
public String getCategory() {
|
||||
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.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
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.BundleRest;
|
||||
import org.dspace.app.rest.model.patch.Patch;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.Bitstream;
|
||||
@@ -34,7 +31,6 @@ import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -71,7 +67,7 @@ public class BitstreamRestRepository extends DSpaceObjectRestRepository<Bitstrea
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasPermission(#id, 'BITSTREAM', 'READ')")
|
||||
@PreAuthorize("hasPermission(#id, 'BITSTREAM', 'METADATA_READ')")
|
||||
public BitstreamRest findOne(Context context, UUID id) {
|
||||
Bitstream bit = null;
|
||||
try {
|
||||
@@ -95,22 +91,7 @@ public class BitstreamRestRepository extends DSpaceObjectRestRepository<Bitstrea
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
public Page<BitstreamRest> findAll(Context context, Pageable pageable) {
|
||||
List<Bitstream> bit = new ArrayList<Bitstream>();
|
||||
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;
|
||||
throw new RepositoryMethodNotImplementedException(BitstreamRest.NAME, "findAll");
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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.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.scripts.Process;
|
||||
import org.dspace.scripts.service.ProcessService;
|
||||
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;
|
||||
|
||||
@@ -32,6 +42,14 @@ public class ProcessRestRepository extends DSpaceRestRepository<ProcessRest, Int
|
||||
@Autowired
|
||||
private ProcessService processService;
|
||||
|
||||
@Autowired
|
||||
private ConverterService converterService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AuthorizeService authorizeService;
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasPermission(#id, 'PROCESS', 'READ')")
|
||||
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
|
||||
public Class<ProcessRest> getDomainClass() {
|
||||
return ProcessRest.class;
|
||||
|
@@ -22,6 +22,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.converter.DSpaceRunnableParameterConverter;
|
||||
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.ProcessRest;
|
||||
import org.dspace.app.rest.model.ScriptRest;
|
||||
@@ -30,6 +31,7 @@ import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||
import org.dspace.scripts.service.ScriptService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* This is the REST repository dealing with the Script logic
|
||||
@@ -56,10 +59,10 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
||||
@PreAuthorize("permitAll()")
|
||||
public ScriptRest findOne(Context context, String name) {
|
||||
|
||||
DSpaceRunnable dSpaceRunnable = scriptService.getScriptForName(name);
|
||||
if (dSpaceRunnable != null) {
|
||||
if (dSpaceRunnable.isAllowedToExecute(context)) {
|
||||
return converter.toRest(dSpaceRunnable, utils.obtainProjection());
|
||||
ScriptConfiguration scriptConfiguration = scriptService.getScriptConfiguration(name);
|
||||
if (scriptConfiguration != null) {
|
||||
if (scriptConfiguration.isAllowedToExecute(context)) {
|
||||
return converter.toRest(scriptConfiguration, utils.obtainProjection());
|
||||
} else {
|
||||
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
|
||||
public Page<ScriptRest> findAll(Context context, Pageable pageable) {
|
||||
List<DSpaceRunnable> dSpaceRunnables = scriptService.getDSpaceRunnables(context);
|
||||
return converter.toRestPage(dSpaceRunnables, pageable, utils.obtainProjection());
|
||||
List<ScriptConfiguration> scriptConfigurations = scriptService.getScriptConfigurations(context);
|
||||
return converter.toRestPage(scriptConfigurations, pageable, utils.obtainProjection());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,12 +89,12 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
||||
* @throws SQLException If something goes wrong
|
||||
* @throws IOException If something goes wrong
|
||||
*/
|
||||
public ProcessRest startProcess(Context context, String scriptName) throws SQLException,
|
||||
IOException, AuthorizeException {
|
||||
public ProcessRest startProcess(Context context, String scriptName, List<MultipartFile> files) throws SQLException,
|
||||
IOException, AuthorizeException, IllegalAccessException, InstantiationException {
|
||||
String properties = requestService.getCurrentRequest().getServletRequest().getParameter("properties");
|
||||
List<DSpaceCommandLineParameter> dSpaceCommandLineParameters =
|
||||
processPropertiesToDSpaceCommandLineParameters(properties);
|
||||
DSpaceRunnable scriptToExecute = scriptService.getScriptForName(scriptName);
|
||||
ScriptConfiguration scriptToExecute = scriptService.getScriptConfiguration(scriptName);
|
||||
if (scriptToExecute == null) {
|
||||
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(
|
||||
context.getCurrentUser(), scriptName, dSpaceCommandLineParameters);
|
||||
List<String> args = constructArgs(dSpaceCommandLineParameters);
|
||||
runDSpaceScript(scriptToExecute, restDSpaceRunnableHandler, args);
|
||||
runDSpaceScript(files, context, scriptToExecute, restDSpaceRunnableHandler, args);
|
||||
return converter.toRest(restDSpaceRunnableHandler.getProcess(context), utils.obtainProjection());
|
||||
}
|
||||
|
||||
@@ -131,13 +134,17 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
|
||||
return args;
|
||||
}
|
||||
|
||||
private void runDSpaceScript(DSpaceRunnable scriptToExecute,
|
||||
RestDSpaceRunnableHandler restDSpaceRunnableHandler, List<String> args) {
|
||||
private void runDSpaceScript(List<MultipartFile> files, Context context, ScriptConfiguration scriptToExecute,
|
||||
RestDSpaceRunnableHandler restDSpaceRunnableHandler, List<String> args)
|
||||
throws IOException, SQLException, AuthorizeException, InstantiationException, IllegalAccessException {
|
||||
DSpaceRunnable dSpaceRunnable = scriptService.createDSpaceRunnableForScriptConfiguration(scriptToExecute);
|
||||
try {
|
||||
scriptToExecute.initialize(args.toArray(new String[0]), restDSpaceRunnableHandler);
|
||||
restDSpaceRunnableHandler.schedule(scriptToExecute);
|
||||
dSpaceRunnable.initialize(args.toArray(new String[0]), restDSpaceRunnableHandler, context.getCurrentUser());
|
||||
checkFileNames(dSpaceRunnable, files);
|
||||
processFiles(context, restDSpaceRunnableHandler, files);
|
||||
restDSpaceRunnableHandler.schedule(dSpaceRunnable);
|
||||
} catch (ParseException e) {
|
||||
scriptToExecute.printHelp();
|
||||
dSpaceRunnable.printHelp();
|
||||
restDSpaceRunnableHandler
|
||||
.handleException(
|
||||
"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) stepClass.newInstance();
|
||||
stepProcessing.doPreProcessing(context, source);
|
||||
stepProcessing.doPatchProcessing(context, getRequestService().getCurrentRequest(), source, op);
|
||||
stepProcessing.doPatchProcessing(context, getRequestService().getCurrentRequest(),
|
||||
source, op, stepConfig);
|
||||
stepProcessing.doPostProcessing(context, source);
|
||||
} else {
|
||||
throw new DSpaceBadRequestException(
|
||||
|
@@ -292,6 +292,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
|
||||
private void evaluatePatch(Context context, HttpServletRequest request, WorkspaceItem source, WorkspaceItemRest wsi,
|
||||
String section, Operation op) {
|
||||
boolean sectionExist = false;
|
||||
SubmissionConfig submissionConfig = submissionConfigReader
|
||||
.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
|
||||
for (int stepNum = 0; stepNum < submissionConfig.getNumberOfSteps(); stepNum++) {
|
||||
@@ -299,6 +300,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
SubmissionStepConfig stepConfig = submissionConfig.getStep(stepNum);
|
||||
|
||||
if (section.equals(stepConfig.getId())) {
|
||||
sectionExist = true;
|
||||
/*
|
||||
* First, load the step processing class (using the current
|
||||
* class loader)
|
||||
@@ -315,7 +317,8 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
AbstractRestProcessingStep stepProcessing =
|
||||
(AbstractRestProcessingStep) stepClass.newInstance();
|
||||
stepProcessing.doPreProcessing(context, source);
|
||||
stepProcessing.doPatchProcessing(context, getRequestService().getCurrentRequest(), source, op);
|
||||
stepProcessing.doPatchProcessing(context,
|
||||
getRequestService().getCurrentRequest(), source, op, stepConfig);
|
||||
stepProcessing.doPostProcessing(context, source);
|
||||
} else {
|
||||
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>!");
|
||||
}
|
||||
|
||||
} catch (UnprocessableEntityException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), 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')")
|
||||
|
@@ -7,16 +7,23 @@
|
||||
*/
|
||||
package org.dspace.app.rest.scripts.handler.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
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.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||
@@ -25,6 +32,8 @@ import org.dspace.scripts.Process;
|
||||
import org.dspace.scripts.factory.ScriptServiceFactory;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
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
|
||||
@@ -33,6 +42,7 @@ public class RestDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager
|
||||
.getLogger(RestDSpaceRunnableHandler.class);
|
||||
|
||||
private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
|
||||
private ProcessService processService = ScriptServiceFactory.getInstance().getProcessService();
|
||||
|
||||
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
|
||||
* @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
|
||||
*/
|
||||
public void schedule(DSpaceRunnable script) {
|
||||
ThreadPoolTaskExecutor taskExecutor = new DSpace().getServiceManager()
|
||||
.getServiceByName("dspaceRunnableThreadExecutor",
|
||||
ThreadPoolTaskExecutor.class);
|
||||
Context context = new Context();
|
||||
try {
|
||||
Process process = processService.find(context, processId);
|
||||
@@ -209,6 +247,6 @@ public class RestDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
||||
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_ACCESSCONDITIONS_OPERATION_ENTRY = "accessConditions";
|
||||
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";
|
||||
|
||||
@@ -94,7 +95,7 @@ public interface AbstractRestProcessingStep extends ListenerProcessingStep {
|
||||
* the json patch operation
|
||||
* @throws Exception
|
||||
*/
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
||||
throws Exception;
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||
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.UploadBitstreamAccessConditionDTO;
|
||||
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.UploadBitstreamRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
@@ -33,6 +34,8 @@ import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.InProgressSubmission;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataValue;
|
||||
import org.dspace.content.WorkspaceItem;
|
||||
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.Context;
|
||||
import org.dspace.core.Utils;
|
||||
import org.dspace.license.service.CreativeCommonsService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.dspace.services.model.Request;
|
||||
@@ -75,6 +79,8 @@ public class SubmissionService {
|
||||
@Autowired
|
||||
protected WorkflowService<XmlWorkflowItem> workflowService;
|
||||
@Autowired
|
||||
protected CreativeCommonsService creativeCommonsService;
|
||||
@Autowired
|
||||
private RequestService requestService;
|
||||
@Autowired
|
||||
private ConverterService converter;
|
||||
@@ -136,19 +142,19 @@ public class SubmissionService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* access conditions (@link {@link UploadBitstreamAccessConditionDTO}
|
||||
*
|
||||
* @param configurationService the DSpace ConfigurationService
|
||||
* @param source the bitstream to translate in its rest submission
|
||||
* representation
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
/**
|
||||
* 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
|
||||
* access conditions (@link {@link UploadBitstreamAccessConditionDTO}
|
||||
*
|
||||
* @param configurationService the DSpace ConfigurationService
|
||||
* @param source the bitstream to translate in its rest submission
|
||||
* representation
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public UploadBitstreamRest buildUploadBitstream(ConfigurationService configurationService, Bitstream source)
|
||||
throws SQLException {
|
||||
throws SQLException {
|
||||
UploadBitstreamRest data = new UploadBitstreamRest();
|
||||
|
||||
for (MetadataValue md : source.getMetadata()) {
|
||||
@@ -242,7 +248,7 @@ public class SubmissionService {
|
||||
wi = workflowService.start(context, wsi);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("The workflow could not be started for workspaceItem with" +
|
||||
"id: " + id);
|
||||
"id: " + id);
|
||||
}
|
||||
|
||||
return wi;
|
||||
@@ -268,4 +274,27 @@ public class SubmissionService {
|
||||
public void saveWorkflowItem(Context context, XmlWorkflowItem source) throws SQLException, AuthorizeException {
|
||||
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.patch.LateObjectEvaluator;
|
||||
import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.InProgressSubmission;
|
||||
@@ -39,12 +40,17 @@ public class BitstreamMetadataValueAddPatchOperation extends MetadataValueAddPat
|
||||
@Autowired
|
||||
ItemService itemService;
|
||||
|
||||
// this is wired in the pring-dspace-core-services.xml
|
||||
BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils;
|
||||
|
||||
@Override
|
||||
void add(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
||||
throws Exception {
|
||||
//"path": "/sections/upload/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();
|
||||
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
||||
;
|
||||
@@ -97,4 +103,8 @@ public class BitstreamMetadataValueAddPatchOperation extends MetadataValueAddPat
|
||||
protected BitstreamService getDSpaceObjectService() {
|
||||
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 org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.InProgressSubmission;
|
||||
@@ -35,12 +36,17 @@ public class BitstreamMetadataValueMovePatchOperation extends MetadataValueMoveP
|
||||
@Autowired
|
||||
ItemService itemService;
|
||||
|
||||
// this is wired in the pring-dspace-core-services.xml
|
||||
BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils;
|
||||
|
||||
@Override
|
||||
void move(Context context, Request currentRequest, InProgressSubmission source, String path, String from)
|
||||
throws Exception {
|
||||
//"path": "/sections/upload/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();
|
||||
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
||||
for (Bundle bb : bundle) {
|
||||
@@ -72,4 +78,7 @@ public class BitstreamMetadataValueMovePatchOperation extends MetadataValueMoveP
|
||||
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 org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.InProgressSubmission;
|
||||
@@ -35,12 +36,17 @@ public class BitstreamMetadataValueRemovePatchOperation extends MetadataValueRem
|
||||
@Autowired
|
||||
ItemService itemService;
|
||||
|
||||
// this is wired in the pring-dspace-core-services.xml
|
||||
BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils;
|
||||
|
||||
@Override
|
||||
void remove(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
||||
throws Exception {
|
||||
//"path": "/sections/upload/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();
|
||||
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
||||
;
|
||||
@@ -67,4 +73,7 @@ public class BitstreamMetadataValueRemovePatchOperation extends MetadataValueRem
|
||||
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.patch.LateObjectEvaluator;
|
||||
import org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.InProgressSubmission;
|
||||
@@ -38,12 +39,17 @@ public class BitstreamMetadataValueReplacePatchOperation extends MetadataValueRe
|
||||
@Autowired
|
||||
ItemService itemService;
|
||||
|
||||
// this is wired in the pring-dspace-core-services.xml
|
||||
BitstreamMetadataValuePathUtils bitstreamMetadataValuePathUtils;
|
||||
|
||||
@Override
|
||||
void replace(Context context, Request currentRequest, InProgressSubmission source, String path, Object value)
|
||||
throws Exception {
|
||||
//"path": "/sections/upload/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();
|
||||
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
|
||||
for (Bundle bb : bundle) {
|
||||
@@ -80,4 +86,8 @@ public class BitstreamMetadataValueReplacePatchOperation extends MetadataValueRe
|
||||
protected BitstreamService getDSpaceObjectService() {
|
||||
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
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
||||
throws Exception {
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||
SubmissionStepConfig stepConf) throws Exception {
|
||||
|
||||
PatchOperation<String> patchOperation = new PatchOperationFactory()
|
||||
.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.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
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.patch.Operation;
|
||||
import org.dspace.app.rest.model.patch.RemoveOperation;
|
||||
import org.dspace.app.rest.model.step.DataDescribe;
|
||||
import org.dspace.app.rest.submit.AbstractRestProcessingStep;
|
||||
import org.dspace.app.rest.submit.SubmissionService;
|
||||
@@ -110,13 +113,56 @@ public class DescribeStep extends org.dspace.submit.step.DescribeStep implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
||||
throws Exception {
|
||||
|
||||
PatchOperation<MetadataValueRest> patchOperation = new PatchOperationFactory()
|
||||
.instanceOf(DESCRIBE_STEP_METADATA_OPERATION_ENTRY, op.getOp());
|
||||
patchOperation.perform(context, currentRequest, source, op);
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||
SubmissionStepConfig stepConf) throws Exception {
|
||||
|
||||
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;
|
||||
|
||||
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.patch.Operation;
|
||||
import org.dspace.app.rest.model.step.DataLicense;
|
||||
@@ -50,8 +51,8 @@ public class LicenseStep extends org.dspace.submit.step.LicenseStep implements A
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
||||
throws Exception {
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||
SubmissionStepConfig stepConf) throws Exception {
|
||||
|
||||
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());
|
||||
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 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.patch.Operation;
|
||||
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);
|
||||
|
||||
public static final String UPLOAD_STEP_METADATA_SECTION = "bitstream-metadata";
|
||||
|
||||
@Override
|
||||
public DataUpload getData(SubmissionService submissionService, InProgressSubmission obj,
|
||||
SubmissionStepConfig config) throws Exception {
|
||||
@@ -61,10 +64,10 @@ public class UploadStep extends org.dspace.submit.step.UploadStep
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op)
|
||||
throws Exception {
|
||||
public void doPatchProcessing(Context context, Request currentRequest, InProgressSubmission source, Operation op,
|
||||
SubmissionStepConfig stepConf) throws Exception {
|
||||
|
||||
String instance = "";
|
||||
String instance = null;
|
||||
if ("remove".equals(op.getOp())) {
|
||||
if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) {
|
||||
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
|
||||
@@ -82,13 +85,16 @@ public class UploadStep extends org.dspace.submit.step.UploadStep
|
||||
} else {
|
||||
if (op.getPath().contains(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;
|
||||
}
|
||||
}
|
||||
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.perform(context, currentRequest, source, op);
|
||||
|
||||
}
|
||||
|
||||
@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 key="bitstreammetadata">
|
||||
<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 key="bitstreammove">
|
||||
<bean
|
||||
@@ -42,7 +44,9 @@
|
||||
</entry>
|
||||
<entry key="bitstreammetadata">
|
||||
<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 key="granted">
|
||||
<bean
|
||||
@@ -52,6 +56,10 @@
|
||||
<bean
|
||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyAddPatchOperation"/>
|
||||
</entry>
|
||||
<entry key="cclicense/uri">
|
||||
<bean
|
||||
class="org.dspace.app.rest.submit.factory.impl.CCLicenseAddPatchOperation"/>
|
||||
</entry>
|
||||
</map>
|
||||
</entry>
|
||||
<entry key="remove">
|
||||
@@ -59,11 +67,13 @@
|
||||
<!-- WARNING do not change "key" it match with Java code (TODO dynamic discover from PATCH operation); -->
|
||||
<entry key="itemmetadata">
|
||||
<bean
|
||||
class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueRemovePatchOperation"/>
|
||||
class="org.dspace.app.rest.submit.factory.impl.ItemMetadataValueRemovePatchOperation" />
|
||||
</entry>
|
||||
<entry key="bitstreammetadata">
|
||||
<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 key="granted">
|
||||
<bean
|
||||
@@ -71,12 +81,16 @@
|
||||
</entry>
|
||||
<entry key="bitstreamremove">
|
||||
<bean
|
||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamRemovePatchOperation"/>
|
||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamRemovePatchOperation" />
|
||||
</entry>
|
||||
<entry key="accessConditions">
|
||||
<bean
|
||||
class="org.dspace.app.rest.submit.factory.impl.BitstreamResourcePolicyRemovePatchOperation"/>
|
||||
</entry>
|
||||
<entry key="cclicense/uri">
|
||||
<bean
|
||||
class="org.dspace.app.rest.submit.factory.impl.CCLicenseRemovePatchOperation"/>
|
||||
</entry>
|
||||
</map>
|
||||
</entry>
|
||||
<entry key="replace">
|
||||
@@ -88,7 +102,9 @@
|
||||
</entry>
|
||||
<entry key="bitstreammetadata">
|
||||
<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 key="granted">
|
||||
<bean
|
||||
@@ -108,4 +124,5 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils" class="org.dspace.app.rest.utils.BitstreamMetadataValuePathUtils"/>
|
||||
</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 -->
|
||||
<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>
|
||||
|
@@ -33,13 +33,14 @@ import org.dspace.app.rest.matcher.BitstreamMatcher;
|
||||
import org.dspace.app.rest.matcher.HalMatcher;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.app.rest.test.MetadataPatchSuite;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -49,6 +50,9 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
@Autowired
|
||||
private BitstreamService bitstreamService;
|
||||
|
||||
@Autowired
|
||||
private ResourcePolicyService resourcePolicyService;
|
||||
|
||||
@Test
|
||||
public void findAllTest() throws Exception {
|
||||
//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);
|
||||
|
||||
getClient(token).perform(get("/api/core/bitstreams/")
|
||||
.param("projection", "full"))
|
||||
.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());
|
||||
getClient(token).perform(get("/api/core/bitstreams/"))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
//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
|
||||
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