/** * 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.curate; import java.io.BufferedReader; import java.io.FileReader; import java.util.Iterator; 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.PosixParser; import org.dspace.content.Site; import org.dspace.core.Context; import org.dspace.core.PluginManager; import org.dspace.eperson.EPerson; /** * CurationCli provides command-line access to Curation tools and processes. * * @author richardrodgers */ public class CurationCli { public static void main(String[] args) throws Exception { // create an options object and populate it CommandLineParser parser = new PosixParser(); Options options = new Options(); options.addOption("t", "task", true, "curation task name"); options.addOption("T", "taskfile", true, "file containing curation task names"); options.addOption("i", "id", true, "Id (handle) of object to perform task on, or 'all' to perform on whole repository"); options.addOption("q", "queue", true, "name of task queue to process"); options.addOption("e", "eperson", true, "email address of curating eperson"); options.addOption("r", "reporter", true, "reporter to manage results - use '-' to report to console. If absent, no reporting"); options.addOption("l", "limit", true, "maximum number of objects allowed in context cache. If absent, no limit"); options.addOption("s", "scope", true, "transaction scope to impose: use 'object', 'curation', or 'open'. If absent, 'open' applies"); options.addOption("v", "verbose", false, "report activity to stdout"); options.addOption("h", "help", false, "help"); CommandLine line = parser.parse(options, args); String taskName = null; String taskFileName = null; String idName = null; String taskQueueName = null; String ePersonName = null; String reporterName = null; String limit = null; String scope = null; boolean verbose = false; if (line.hasOption('h')) { HelpFormatter help = new HelpFormatter(); help.printHelp("CurationCli\n", options); System.out .println("\nwhole repo: CurationCli -t estimate -i all"); System.out .println("single item: CurationCli -t generate -i itemId"); System.out .println("task queue: CurationCli -q monthly"); System.exit(0); } if (line.hasOption('t')) { // task taskName = line.getOptionValue('t'); } if (line.hasOption('T')) { // task file taskFileName = line.getOptionValue('T'); } if (line.hasOption('i')) { // id idName = line.getOptionValue('i'); } if (line.hasOption('q')) { // task queue taskQueueName = line.getOptionValue('q'); } if (line.hasOption('e')) { // eperson ePersonName = line.getOptionValue('e'); } if (line.hasOption('r')) { // report file reporterName = line.getOptionValue('r'); } if (line.hasOption('l')) { // cache limit limit = line.getOptionValue('l'); } if (line.hasOption('s')) { // transaction scope scope = line.getOptionValue('s'); } if (line.hasOption('v')) { // verbose verbose = true; } // now validate the args if (idName == null && taskQueueName == null) { System.out.println("Id must be specified: a handle, 'all', or a task queue (-h for help)"); System.exit(1); } if (taskName == null && taskFileName == null && taskQueueName == null) { System.out.println("A curation task or queue must be specified (-h for help)"); System.exit(1); } if (limit != null && Integer.parseInt(limit) <= 0 ) { System.out.println("Cache limit '" + limit + "' must be a positive integer"); System.exit(1); } if (scope != null && Curator.TxScope.valueOf(scope.toUpperCase()) == null) { System.out.println("Bad transaction scope '" + scope + "': only 'object', 'curation' or 'open' recognized"); System.exit(1); } Context c = new Context(); if (ePersonName != null) { EPerson ePerson = EPerson.findByEmail(c, ePersonName); if (ePerson == null) { System.out.println("EPerson not found: " + ePersonName); System.exit(1); } c.setCurrentUser(ePerson); } else { c.setIgnoreAuthorization(true); } Curator curator = new Curator(); if (reporterName != null) { curator.setReporter(reporterName); } if (limit != null) { curator.setCacheLimit(Integer.parseInt(limit)); } if (scope != null) { Curator.TxScope txScope = Curator.TxScope.valueOf(scope.toUpperCase()); curator.setTransactionScope(txScope); } // we are operating in batch mode, if anyone cares. curator.setInvoked(Curator.Invoked.BATCH); // load curation tasks if (taskName != null) { if (verbose) { System.out.println("Adding task: " + taskName); } curator.addTask(taskName); if (verbose && ! curator.hasTask(taskName)) { System.out.println("Task: " + taskName + " not resolved"); } } else if (taskQueueName == null) { // load taskFile BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(taskFileName)); while ((taskName = reader.readLine()) != null) { if (verbose) { System.out.println("Adding task: " + taskName); } curator.addTask(taskName); } } finally { if (reader != null) { reader.close(); } } } // run tasks against object long start = System.currentTimeMillis(); if (verbose) { System.out.println("Starting curation"); } if (idName != null) { if (verbose) { System.out.println("Curating id: " + idName); } if ("all".equals(idName)) { // run on whole Site curator.curate(c, Site.getSiteHandle()); } else { curator.curate(c, idName); } } else { // process the task queue TaskQueue queue = (TaskQueue)PluginManager.getSinglePlugin("curate", TaskQueue.class); if (queue == null) { System.out.println("No implementation configured for queue"); throw new UnsupportedOperationException("No queue service available"); } // use current time as our reader 'ticket' long ticket = System.currentTimeMillis(); Iterator<TaskQueueEntry> entryIter = queue.dequeue(taskQueueName, ticket).iterator(); while (entryIter.hasNext()) { TaskQueueEntry entry = entryIter.next(); if (verbose) { System.out.println("Curating id: " + entry.getObjectId()); } curator.clear(); // does entry relate to a DSO or workflow object? if (entry.getObjectId().indexOf("/") > 0) { for (String task : entry.getTaskNames()) { curator.addTask(task); } curator.curate(c, entry.getObjectId()); } else { // make eperson who queued task the effective user EPerson agent = EPerson.findByEmail(c, entry.getEpersonId()); if (agent != null) { c.setCurrentUser(agent); } WorkflowCurator.curate(curator, c, entry.getObjectId()); } } queue.release(taskQueueName, ticket, true); } c.complete(); if (verbose) { long elapsed = System.currentTimeMillis() - start; System.out.println("Ending curation. Elapsed time: " + elapsed); } } }