package net.sourceforge.seqware.pipeline.module;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import joptsimple.OptionParser;
import net.sourceforge.seqware.common.metadata.Metadata;
import net.sourceforge.seqware.common.module.ReturnValue;
import net.sourceforge.seqware.common.util.Log;
/**
* <p>
* Abstract Module class.
* </p>
*
* @author boconnor
* @version $Id: $Id
*/
public abstract class Module implements ModuleInterface {
// Data Members
Metadata metadata;
// a universal place for all modules to reference the version number
// this is important because modules may be calling command line tools from
// other seqware projects so they need to know what version they are so they
// know what versions of the other SeqWare tools they are compatible with
/** Constant <code>VERSION="0.7.0"</code> */
public static final String VERSION = "0.7.0";
// FIXME: need to add javadocs for everything. What is the best way to do
// things so we don't have redundancy between javadocs and get_syntax
// FIXME: Nothing should write to stderr/stdout. Instead should return to
// runner through an object, and runner should print it.
// FIXME: Need to look at unit testing with TestNG and Log4J for logging.
// TestNG is compile time tests. Might also have stuff that will be helpful
// for do_test()
String algorithm;
File stdoutFile;
File stderrFile;
protected int processingAccession;
List<String> parameters = new ArrayList<>();
/**
* Getter for the file where the stdout will be redirected. By default, the stdout will be redirected before the do_run() method and
* turned off after do_run() method. However, this can be changed via the @StdoutRedirect annotation on the module class
*
* @return the stdout file object
*/
public File getStdoutFile() {
return stdoutFile;
}
/**
* <p>
* Setter for the field <code>stdoutFile</code>.
* </p>
*
* @param stdoutFile
* a {@link java.io.File} object.
*/
public void setStdoutFile(File stdoutFile) {
this.stdoutFile = stdoutFile;
}
/**
* Getter for the file where the stderr will be redirected. By default, the stderr will be redirected before the do_run() method and
* turned off after the do_run(). To change the behavior, use @StderrRedirect annotation.
*
* @return the stderr file object
*/
public File getStderrFile() {
return stderrFile;
}
/**
* Added by Xiaoshu Wang: Setter for the file that will be used to redirect stderr
*
* @param stderrFile
* the stderr file object
*/
public void setStderrFile(File stderrFile) {
this.stderrFile = stderrFile;
}
/**
* <p>
* Getter for the field <code>metadata</code>.
* </p>
*
* @return a {@link net.sourceforge.seqware.common.metadata.Metadata} object.
*/
public Metadata getMetadata() {
return metadata;
}
/**
* <p>
* Getter for the field <code>algorithm</code>.
* </p>
*
* @return a {@link java.lang.String} object.
*/
@Override
public String getAlgorithm() {
return algorithm;
}
/**
* <p>
* Setter for the field <code>algorithm</code>.
* </p>
*
* @param algorithm
* a {@link java.lang.String} object.
*/
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
/**
* <p>
* Setter for the field <code>metadata</code>.
* </p>
*
* @param metadata
* a {@link net.sourceforge.seqware.common.metadata.Metadata} object.
*/
public void setMetadata(Metadata metadata) {
this.metadata = metadata;
}
/**
* <p>
* Getter for the field <code>parameters</code>.
* </p>
*
* @return a {@link java.util.List} object.
*/
public List<String> getParameters() {
return parameters;
}
/**
* {@inheritDoc}
*
* This method doesn't just copy the list, it actually parses through the list and looks for values that start with " or ' and then
* attempts to merge other parameters separated by space until an param ending with " or ' is found. This is to work around a limitation
* in JOpt. It breaks apart arguments by space regarless if the arg is a quoted string (and hence should be treated as one arg)
*
* @param parameters
*/
@Override
public void setParameters(List<String> parameters) {
Log.info("Parsing Command Parameters:");
// Clear the parameters first. Otherwise, it will have side effect when
// setParameters are called twice, the parameters
// are merged as opposed to be set
this.parameters.clear();
boolean readingQuoteString = false;
String quoteString = null;
StringBuffer buffer = new StringBuffer();
for (String param : parameters) {
// I may have encoded this string to prevent bash/pegasus interpretation
param = param.replaceAll(""", "\"");
param = param.replaceAll("'", "'");
param = param.replaceAll(">", ">");
param = param.replaceAll("<", "<");
param = param.replaceAll("&", "&");
param = param.replaceAll("*", "*");
// FIXME: had to use my own escape sequence to get it through XML parsing
// of the DAX!
param = param.replaceAll("~quot;", "\"");
param = param.replaceAll("~apos;", "'");
param = param.replaceAll("~gt;", ">");
param = param.replaceAll("~lt;", "<");
param = param.replaceAll("~amp;", "&");
param = param.replaceAll("~#42;", "*");
param = param.replaceAll("~star;", "*");
// Log.info("Param Parser: "+param);
if (readingQuoteString && !param.endsWith(quoteString)) {
buffer.append(" ").append(param);
} else if (param.startsWith("\"") && !readingQuoteString) {
quoteString = "\"";
readingQuoteString = true;
buffer.append(param.substring(1));
} else if (param.startsWith("'") && !param.endsWith("'") && !readingQuoteString) {
quoteString = "'";
readingQuoteString = true;
buffer.append(param.substring(1));
} else if (readingQuoteString && param.endsWith(quoteString)) {
buffer.append(" ").append(param.substring(0, param.length() - 1));
readingQuoteString = false;
quoteString = null;
Log.info(" param: " + buffer.toString());
this.parameters.add(buffer.toString());
buffer = new StringBuffer();
} else {
Log.info(" param: " + param);
this.parameters.add(param);
}
}
}
/**
* <p>
* getOptionParser.
* </p>
*
* @return a {@link joptsimple.OptionParser} object.
*/
protected OptionParser getOptionParser() {
OptionParser parser = null;
return (parser);
}
/**
* {@inheritDoc}
*
* A method used to return the syntax for this module
*/
@Override
public String get_syntax() {
OptionParser parser = getOptionParser();
if (parser == null) {
return "Sorry, no help information available";
}
StringWriter output = new StringWriter();
try {
parser.printHelpOn(output);
} catch (IOException e) {
e.printStackTrace();
return (e.getMessage());
}
return (output.toString());
}
/**
* Output Galaxy definition files so you can use this module with Galaxy. See
* http://bitbucket.org/galaxy/galaxy-central/wiki/AddToolTutorial
*
* @return a {@link java.lang.String} object.
*/
public String get_galaxy_xml() {
OptionParser parser = getOptionParser();
if (parser == null) {
return "Sorry, no module paramater information available so I can't make a Galaxy XML.";
}
StringWriter output = new StringWriter();
try {
// left off here, need to look at the options that are available
parser.printHelpOn(output);
} catch (IOException e) {
e.printStackTrace();
return (e.getMessage());
}
return (output.toString());
}
// Do_run must be implemented, or else object is useless
/**
* <p>
* do_run.
* </p>
*
* @return a {@link net.sourceforge.seqware.common.module.ReturnValue} object.
*/
@Override
public abstract ReturnValue do_run();
// Default member functions member functions
/**
* <p>
* init.
* </p>
*
* @return a {@link net.sourceforge.seqware.common.module.ReturnValue} object.
*/
@Override
public ReturnValue init() {
return ReturnValue.featureNotImplemented();
}
/**
* <p>
* clean_up.
* </p>
*
* @return a {@link net.sourceforge.seqware.common.module.ReturnValue} object.
*/
@Override
public ReturnValue clean_up() {
return ReturnValue.featureNotImplemented();
}
/**
* <p>
* do_test.
* </p>
*
* @return a {@link net.sourceforge.seqware.common.module.ReturnValue} object.
*/
@Override
public abstract ReturnValue do_test();
/**
* <p>
* do_verify_input.
* </p>
*
* @return a {@link net.sourceforge.seqware.common.module.ReturnValue} object.
*/
@Override
public abstract ReturnValue do_verify_input();
/**
* <p>
* do_verify_parameters.
* </p>
*
* @return a {@link net.sourceforge.seqware.common.module.ReturnValue} object.
*/
@Override
public abstract ReturnValue do_verify_parameters();
/**
* <p>
* do_verify_output.
* </p>
*
* @return a {@link net.sourceforge.seqware.common.module.ReturnValue} object.
*/
@Override
public abstract ReturnValue do_verify_output();
/**
* <p>
* Getter for the field <code>processingAccession</code>.
* </p>
*
* @return a int.
*/
public int getProcessingAccession() {
return this.processingAccession;
}
/**
* <p>
* Setter for the field <code>processingAccession</code>.
* </p>
*
* @param accession
* a int.
*/
public void setProcessingAccession(int accession) {
this.processingAccession = accession;
}
}