package edu.sc.seis.sod;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.martiansoftware.jsap.Flagged;
import com.martiansoftware.jsap.FlaggedOption;
import com.martiansoftware.jsap.JSAP;
import com.martiansoftware.jsap.JSAPException;
import com.martiansoftware.jsap.JSAPResult;
import com.martiansoftware.jsap.Parameter;
import com.martiansoftware.jsap.ParseException;
import com.martiansoftware.jsap.StringParser;
import com.martiansoftware.jsap.Switch;
import edu.sc.seis.fissuresUtil.simple.Initializer;
public class Args {
private static final String COMMAND_NAME = "sod";
public Args(String[] args) throws JSAPException {
this.args = args;
List<String> toParse = new ArrayList<String>(args.length);
for(int i = 0; i < args.length; i++) {
if(args[i].equals("-conf")) {
args[i] = "-f";
}
for(int j = 0; j < Initializer.POSSIBLE_PROP_OPTION_NAMES.length; j++) {
if(args[i].equals(Initializer.POSSIBLE_PROP_OPTION_NAMES[j])) {
args[i] = "-p";
}
}
if(args[i].equals("-demo") || args[i].equals("--demo")) {
// replace demo with a like -f command
toParse.add("-f");
toParse.add(Start.TUTORIAL_LOC);
} else if(args[i].equals("-hsql")) {
// Skip over -hsql and its argument
i++;
} else {
toParse.add(args[i]);
}
}
add(new Switch("debug", JSAP.NO_SHORTFLAG, "debug", "extra debug output to log file"));
add(new Switch("help", 'h', "help", "Print out this message"));
add(new Switch("event-arm", 'e', "event-arm", "Only run the event arm"));
add(new Switch("network-arm",
'n',
"network-arm",
"Only run the network arm"));
add(new Switch("validate",
'V',
"validate",
"Validate the recipe and exit"));
add(new Switch(CLEAN_SWITCH,
'c',
CLEAN_SWITCH,
"Clean the database before starting, any existing results are lost."));
add(new Switch("quick",
'q',
"quick",
"Run quick and dirty, the database is not saved to disk, hence no crash recovery"));
add(new Switch("invalid",
'i',
"invalid",
"The recipe is known to be invalid so skip the 10 second wait"));
add(new Switch(PRINT_RECIPE_SWITCH,
'r',
PRINT_RECIPE_SWITCH,
"Print the created recipe to stdout instead of running it"));
add(new Switch("replace-recipe",
JSAP.NO_SHORTFLAG,
"replace-recipe",
"Replace the recipe in the db with this one"));
add(new Switch("version",
'v',
"version",
"Print SOD's version and exit"));
add(new Switch(QUIT_ON_ERROR_SWITCH,
JSAP.NO_SHORTFLAG,
QUIT_ON_ERROR_SWITCH,
"Exit on the first error instead of retrying"));
add(new FlaggedOption("props",
new FileParser(),
null,
false,
'p',
"props",
"A properties file to configure SOD"));
add(new FlaggedOption("recipe",
JSAP.STRING_PARSER,
null,
true,
'f',
"recipe",
"The recipe to run"));
add(new Switch("demo",
JSAP.NO_SHORTFLAG,
"demo",
"Run an demo recipe. Use with -r to see the demo recipe."));
result = jsap.parse((String[])toParse.toArray(new String[0]));
if(result.getBoolean("version")) {
System.out.println("SOD " + Version.current().getVersion());
System.exit(0);
}
if(result.getBoolean("help")) {
System.err.println(makeHelp(COMMAND_NAME, parameters));
System.exit(0);
}
if(result.userSpecified("event-arm")
&& result.userSpecified("network-arm")) {
result.addException("General",
new RuntimeException("Only one of -e and -n may be specified"));
}
if(!result.success()) {
Start.exit(makeError(COMMAND_NAME, parameters, result));
}
}
public static String makeUsage(String command, List params) {
StringBuffer builder = new StringBuffer("Usage: " + command + " [-");
Iterator it = params.iterator();
while(it.hasNext()) {
Parameter p = (Parameter)it.next();
if(p instanceof Switch
&& ((Switch)p).getShortFlagCharacter() != null) {
builder.append(((Switch)p).getShortFlagCharacter());
}
}
builder.append("] ");
it = params.iterator();
while(it.hasNext()) {
Parameter p = (Parameter)it.next();
if(p instanceof FlaggedOption) {
FlaggedOption fo = (FlaggedOption)p;
if(!fo.required()) {
builder.append('[');
}
if(((FlaggedOption)p).getShortFlag() != JSAP.NO_SHORTFLAG) {
builder.append('-');
builder.append(((FlaggedOption)p).getShortFlag());
} else {
builder.append("--");
builder.append(((FlaggedOption)p).getLongFlag());
}
builder.append(" <");
builder.append(p.getID());
builder.append('>');
if(!fo.required()) {
builder.append(']');
}
builder.append(' ');
}
}
builder.append('\n');
return builder.toString();
}
public static String makeHelp(String command, List params) {
StringBuffer buff = new StringBuffer();
buff.append(makeUsage(command, params));
buff.append('\n');
Iterator it = params.iterator();
while(it.hasNext()) {
Parameter sw = (Parameter)it.next();
buff.append(" ");
if(((Flagged)sw).getShortFlag() != JSAP.NO_SHORTFLAG) {
buff.append('-');
buff.append(((Flagged)sw).getShortFlag());
buff.append('/');
}
buff.append("--");
buff.append(((Flagged)sw).getLongFlag());
buff.append(' ');
if(sw instanceof FlaggedOption) {
FlaggedOption fo = (FlaggedOption)sw;
if(fo.isList()) {
buff.append(fo.getShortFlag());
buff.append("1,");
buff.append(fo.getShortFlag());
buff.append("2,...,");
buff.append(fo.getShortFlag());
buff.append('n');
} else {
buff.append('<');
buff.append(sw.getID());
buff.append('>');
}
}
buff.append(" ");
buff.append(sw.getHelp());
buff.append('\n');
}
return buff.toString();
}
public static String makeError(String command,
List params,
JSAPResult result) {
StringBuffer buff = new StringBuffer();
buff.append(Args.makeUsage(command, params));
buff.append('\n');
Iterator it = result.getErrorMessageIterator();
while(it.hasNext()) {
buff.append(it.next());
buff.append('\n');
}
return buff.toString();
}
private void add(Parameter p) throws JSAPException {
jsap.registerParameter(p);
parameters.add(p);
}
public boolean hasProps() {
return result.contains("props");
}
public InputStream getProps() {
try {
return new BufferedInputStream(new FileInputStream(result.getFile("props")));
} catch(FileNotFoundException e) {
throw new RuntimeException(e);
}
}
public String[] getInitialArgs() {
return args;
}
public String getRecipe() {
return result.getString("recipe");
}
public boolean isQuickAndDirty() {
return result.getBoolean("quick");
}
public boolean isQuitOnError() {
return result.getBoolean(QUIT_ON_ERROR_SWITCH);
}
public boolean isClean() {
return result.getBoolean(CLEAN_SWITCH);
}
public boolean isPrintRecipe() {
return result.getBoolean(PRINT_RECIPE_SWITCH);
}
public boolean isDebug() {
return result.getBoolean("debug");
}
public boolean onlyValidate() {
return result.getBoolean("validate");
}
public boolean doEventArm() {
return result.getBoolean("event-arm")
|| !result.getBoolean("network-arm");
}
public boolean doNetArm() {
return !result.getBoolean("event-arm")
|| result.getBoolean("network-arm");
}
public boolean doWaveformArm() {
return !result.getBoolean("event-arm")
&& !result.getBoolean("network-arm");
}
public boolean waitOnError() {
return !onlyValidate() && !result.getBoolean("invalid");
}
public boolean replaceDBConfig() {
return result.getBoolean("replace-recipe");
}
private JSAPResult result;
private JSAP jsap = new JSAP();
private List parameters = new ArrayList();
private String[] args;
private static class FileParser extends StringParser {
public Object parse(String arg) throws ParseException {
File f = new File(arg);
if(!f.exists()) {
throw new ParseException("'" + arg + "' doesn't exist");
}
return f;
}
}
public String toString() {
String out = "";
for (int i = 0; i < args.length; i++) {
out += " "+args[i];
}
return out;
}
public static final String CLEAN_SWITCH = "clean";
public static final String QUIT_ON_ERROR_SWITCH = "quitOnError";
public static final String PRINT_RECIPE_SWITCH = "print-recipe";
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Args.class);
}