/**
* 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);
}
}
}