diff --git a/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java b/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java index bbf320a0d5..d503bfc00b 100644 --- a/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java +++ b/dspace-api/src/main/java/org/dspace/administer/RegistryLoader.java @@ -21,6 +21,13 @@ import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.BitstreamFormat; @@ -41,7 +48,7 @@ import org.xml.sax.SAXException; *
* RegistryLoader -bitstream bitstream-formats.xml
*
- * RegistryLoader -dc dc-types.xml
+ * RegistryLoader -metadata dc-types.xml
*
* @author Robert Tansley
* @version $Revision$
@@ -50,7 +57,7 @@ public class RegistryLoader {
/**
* log4j category
*/
- private static Logger log = org.apache.logging.log4j.LogManager.getLogger(RegistryLoader.class);
+ private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RegistryLoader.class);
protected static BitstreamFormatService bitstreamFormatService = ContentServiceFactory.getInstance()
.getBitstreamFormatService();
@@ -67,50 +74,99 @@ public class RegistryLoader {
* @throws Exception if error
*/
public static void main(String[] argv) throws Exception {
- String usage = "Usage: " + RegistryLoader.class.getName()
- + " (-bitstream | -metadata) registry-file.xml";
-
- Context context = null;
+ // Set up command-line options and parse arguments
+ CommandLineParser parser = new DefaultParser();
+ Options options = createCommandLineOptions();
try {
- context = new Context();
+ CommandLine line = parser.parse(options, argv);
+
+ // Check if help option was entered or no options provided
+ if (line.hasOption('h') || line.getOptions().length == 0) {
+ printHelp(options);
+ System.exit(0);
+ }
+
+ Context context = new Context();
// Can't update registries anonymously, so we need to turn off
// authorisation
context.turnOffAuthorisationSystem();
- // Work out what we're loading
- if (argv[0].equalsIgnoreCase("-bitstream")) {
- RegistryLoader.loadBitstreamFormats(context, argv[1]);
- } else if (argv[0].equalsIgnoreCase("-metadata")) {
- // Call MetadataImporter, as it handles Metadata schema updates
- MetadataImporter.loadRegistry(argv[1], true);
- } else {
- System.err.println(usage);
+ try {
+ // Work out what we're loading
+ if (line.hasOption('b')) {
+ String filename = line.getOptionValue('b');
+ if (StringUtils.isEmpty(filename)) {
+ System.err.println("No file path provided for bitstream format registry");
+ printHelp(options);
+ System.exit(1);
+ }
+ RegistryLoader.loadBitstreamFormats(context, filename);
+ } else if (line.hasOption('m')) {
+ String filename = line.getOptionValue('m');
+ if (StringUtils.isEmpty(filename)) {
+ System.err.println("No file path provided for metadata registry");
+ printHelp(options);
+ System.exit(1);
+ }
+ // Call MetadataImporter, as it handles Metadata schema updates
+ MetadataImporter.loadRegistry(filename, true);
+ } else {
+ System.err.println("No registry type specified");
+ printHelp(options);
+ System.exit(1);
+ }
+
+ // Commit changes and close Context
+ context.complete();
+ System.exit(0);
+ } catch (Exception e) {
+ log.fatal(LogHelper.getHeader(context, "error_loading_registries", ""), e);
+ System.err.println("Error: \n - " + e.getMessage());
+ System.exit(1);
+ } finally {
+ // Clean up our context, if it still exists & it was never completed
+ if (context != null && context.isValid()) {
+ context.abort();
+ }
}
-
- // Commit changes and close Context
- context.complete();
-
- System.exit(0);
- } catch (ArrayIndexOutOfBoundsException ae) {
- System.err.println(usage);
-
+ } catch (ParseException e) {
+ System.err.println("Error parsing command-line arguments: " + e.getMessage());
+ printHelp(options);
System.exit(1);
- } catch (Exception e) {
- log.fatal(LogHelper.getHeader(context, "error_loading_registries",
- ""), e);
-
- System.err.println("Error: \n - " + e.getMessage());
- System.exit(1);
- } finally {
- // Clean up our context, if it still exists & it was never completed
- if (context != null && context.isValid()) {
- context.abort();
- }
}
}
+ /**
+ * Create the command-line options
+ * @return the command-line options
+ */
+ private static Options createCommandLineOptions() {
+ Options options = new Options();
+
+ options.addOption("b", "bitstream", true, "load bitstream format registry from specified file");
+ options.addOption("m", "metadata", true, "load metadata registry from specified file");
+ options.addOption("h", "help", false, "print this help message");
+
+ return options;
+ }
+
+ /**
+ * Print the help message
+ * @param options the command-line options
+ */
+ private static void printHelp(Options options) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("RegistryLoader",
+ "Load bitstream format or metadata registries into the database\n",
+ options,
+ "\nExamples:\n" +
+ " RegistryLoader -b bitstream-formats.xml\n" +
+ " RegistryLoader -m dc-types.xml",
+ true);
+ }
+
/**
* Load Bitstream Format metadata
*
@@ -221,7 +277,7 @@ public class RegistryLoader {
* contains:
*
*
- * <foo><mimetype>application/pdf</mimetype></foo>
+ *
* passing this the foo
node and mimetype
will
* return application/pdf
.
@@ -262,10 +318,10 @@ public class RegistryLoader {
* document contains:
*
*
- * <foo>
- * <bar>val1</bar>
- * <bar>val2</bar>
- * </foo>
+ *
* passing this the foo
node and bar
will
* return val1
and val2
.
@@ -295,4 +351,4 @@ public class RegistryLoader {
return data;
}
-}
+}
\ No newline at end of file
diff --git a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java
index e8c5d93181..e53d29ecfb 100644
--- a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java
+++ b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java
@@ -64,20 +64,36 @@ public class InitializeEntities {
*/
public static void main(String[] argv) throws SQLException, AuthorizeException, ParseException {
InitializeEntities initializeEntities = new InitializeEntities();
+ // Set up command-line options and parse arguments
CommandLineParser parser = new DefaultParser();
Options options = createCommandLineOptions();
CommandLine line = parser.parse(options,argv);
- String fileLocation = getFileLocationFromCommandLine(line);
+ // First of all, check if the help option was entered or a required argument is missing
checkHelpEntered(options, line);
+ // Get the file location from the command line
+ String fileLocation = getFileLocationFromCommandLine(line);
+ // Run the script
initializeEntities.run(fileLocation);
}
+
+ /**
+ * Check if the help option was entered or a required argument is missing. If so, print help and exit.
+ * @param options the defined command-line options
+ * @param line the parsed command-line arguments
+ */
private static void checkHelpEntered(Options options, CommandLine line) {
- if (line.hasOption("h")) {
+ if (line.hasOption("h") || !line.hasOption("f")) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("Initialize Entities", options);
System.exit(0);
}
}
+
+ /**
+ * Get the file path from the command-line argument. Exits with exit code 1 if no file argument was entered.
+ * @param line the parsed command-line arguments
+ * @return the file path
+ */
private static String getFileLocationFromCommandLine(CommandLine line) {
String query = line.getOptionValue("f");
if (StringUtils.isEmpty(query)) {
@@ -88,13 +104,25 @@ public class InitializeEntities {
return query;
}
+ /**
+ * Create the command-line options
+ * @return the command-line options
+ */
protected static Options createCommandLineOptions() {
Options options = new Options();
- options.addOption("f", "file", true, "the location for the file containing the xml data");
+ options.addOption("f", "file", true, "the path to the file containing the " +
+ "relationship definitions (e.g. ${dspace.dir}/config/entities/relationship-types.xml)");
+ options.addOption("h", "help", false, "print this message");
return options;
}
+ /**
+ * Run the script for the given file location
+ * @param fileLocation the file location
+ * @throws SQLException If something goes wrong initializing context or inserting relationship types
+ * @throws AuthorizeException If the script user fails to authorize while inserting relationship types
+ */
private void run(String fileLocation) throws SQLException, AuthorizeException {
Context context = new Context();
context.turnOffAuthorisationSystem();
@@ -102,6 +130,12 @@ public class InitializeEntities {
context.complete();
}
+ /**
+ * Parse the XML file at fileLocation to create relationship types in the database
+ * @param context DSpace context
+ * @param fileLocation the full or relative file path to the relationship types XML
+ * @throws AuthorizeException If the script user fails to authorize while inserting relationship types
+ */
private void parseXMLToRelations(Context context, String fileLocation) throws AuthorizeException {
try {
File fXmlFile = new File(fileLocation);
@@ -158,15 +192,15 @@ public class InitializeEntities {
for (int j = 0; j < leftCardinalityList.getLength(); j++) {
Node node = leftCardinalityList.item(j);
- leftCardinalityMin = getString(leftCardinalityMin,(Element) node, "min");
- leftCardinalityMax = getString(leftCardinalityMax,(Element) node, "max");
+ leftCardinalityMin = getCardinalityMinString(leftCardinalityMin,(Element) node, "min");
+ leftCardinalityMax = getCardinalityMinString(leftCardinalityMax,(Element) node, "max");
}
for (int j = 0; j < rightCardinalityList.getLength(); j++) {
Node node = rightCardinalityList.item(j);
- rightCardinalityMin = getString(rightCardinalityMin,(Element) node, "min");
- rightCardinalityMax = getString(rightCardinalityMax,(Element) node, "max");
+ rightCardinalityMin = getCardinalityMinString(rightCardinalityMin,(Element) node, "min");
+ rightCardinalityMax = getCardinalityMinString(rightCardinalityMax,(Element) node, "max");
}
populateRelationshipType(context, leftType, rightType, leftwardType, rightwardType,
@@ -182,13 +216,39 @@ public class InitializeEntities {
}
}
- private String getString(String leftCardinalityMin,Element node, String minOrMax) {
+ /**
+ * Extract the min or max value for the left or right cardinality from the node text content
+ * @param leftCardinalityMin current left cardinality min
+ * @param node node to extract the min or max value from
+ * @param minOrMax element tag name to parse
+ * @return final left cardinality min
+ */
+ private String getCardinalityMinString(String leftCardinalityMin, Element node, String minOrMax) {
if (node.getElementsByTagName(minOrMax).getLength() > 0) {
leftCardinalityMin = node.getElementsByTagName(minOrMax).item(0).getTextContent();
}
return leftCardinalityMin;
}
+ /**
+ * Populate the relationship type based on values parsed from the XML relationship types configuration
+ *
+ * @param context DSpace context
+ * @param leftType left relationship type (e.g. "Publication").
+ * @param rightType right relationship type (e.g. "Journal").
+ * @param leftwardType leftward relationship type (e.g. "isAuthorOfPublication").
+ * @param rightwardType rightward relationship type (e.g. "isPublicationOfAuthor").
+ * @param leftCardinalityMin left cardinality min
+ * @param leftCardinalityMax left cardinality max
+ * @param rightCardinalityMin right cardinality min
+ * @param rightCardinalityMax right cardinality max
+ * @param copyToLeft copy metadata values to left if right side is deleted
+ * @param copyToRight copy metadata values to right if left side is deleted
+ * @param tilted set a tilted relationship side (left or right) if there are many relationships going one way
+ * to help performance (e.g. authors with 1000s of publications)
+ * @throws SQLException if database error occurs while saving the relationship type
+ * @throws AuthorizeException if authorization error occurs while saving the relationship type
+ */
private void populateRelationshipType(Context context, String leftType, String rightType, String leftwardType,
String rightwardType, String leftCardinalityMin, String leftCardinalityMax,
String rightCardinalityMin, String rightCardinalityMax,
diff --git a/dspace-api/src/main/java/org/dspace/curate/Curation.java b/dspace-api/src/main/java/org/dspace/curate/Curation.java
index 52bb3e4fa0..a2b4bc482a 100644
--- a/dspace-api/src/main/java/org/dspace/curate/Curation.java
+++ b/dspace-api/src/main/java/org/dspace/curate/Curation.java
@@ -25,6 +25,8 @@ import java.util.UUID;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.output.NullOutputStream;
+import org.dspace.app.util.DSpaceObjectUtilsImpl;
+import org.dspace.app.util.service.DSpaceObjectUtils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
import org.dspace.content.factory.ContentServiceFactory;
@@ -36,6 +38,7 @@ import org.dspace.eperson.service.EPersonService;
import org.dspace.handle.factory.HandleServiceFactory;
import org.dspace.handle.service.HandleService;
import org.dspace.scripts.DSpaceRunnable;
+import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.utils.DSpace;
/**
@@ -46,7 +49,9 @@ import org.dspace.utils.DSpace;
public class Curation extends DSpaceRunnable