package edu.sc.seis.sod.subsetter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.w3c.dom.Element;
import edu.sc.seis.bag.Bag;
import edu.sc.seis.sod.SodUtil;
import edu.sc.seis.sod.Start;
import edu.sc.seis.sod.status.Pass;
import edu.sc.seis.sod.status.StringTree;
import edu.sc.seis.sod.status.StringTreeLeaf;
public class AbstractScriptSubsetter implements Subsetter {
public AbstractScriptSubsetter(Element config) {
this.config = config;
scriptType = config.getAttribute("type");
engine = factory.getEngineByName(scriptType);
script = cleanScript(SodUtil.getNestedText(config));
}
protected Object preeval() throws Exception {
try {
if (scriptType.equals("jython") || scriptType.equals("python")) {
engine.eval("import sys");
engine.eval("sys.path.append('" + Bag.formatForJythonSysPath(Bag.class, "edu/sc/seis/bag/jython")
+ "')");
engine.eval("from bag import *");
}
engine.put("result", new Pass(this));
engine.put("util", new ScriptUtil(this));
Object result = engine.eval(script);
return result;// might be null
} catch(ScriptException e) {
logger.error("Problem in script: \n-------------|\n" + script + "|-------", e);
Start.exit("Problem in script: \n-------------|\n" + script + "|-------\n\n" + e);
// never get here...
throw new RuntimeException();
}
}
protected Object pullResult(Object result) throws Exception {
if (result == null) {
// try getting variable named result from engine
result = engine.get("result");
}
if (result == null) {
// assume all well and return a Pass
return new Pass(this);
}
if (result instanceof StringTree) {
return (StringTree)result;
} else if (result instanceof Boolean) {
return new StringTreeLeaf(this, ((Boolean)result).booleanValue());
} else {
throw new UnknownScriptResult("Script returns unknown results type, should be boolean or StringTree: " + result.toString());
}
}
protected StringTree eval() throws Exception {
return (StringTree)pullResult(preeval());
}
public static String cleanScript(String script) {
if (script.indexOf("\n") == -1) {
// one line
return script.trim();
}
String trimBegEnd = script;
// clean blank lines from beginning
Matcher matcher = Pattern.compile("(?: *\\n)+(.*)", Pattern.DOTALL).matcher(trimBegEnd);
if (matcher.matches()) {
trimBegEnd = matcher.group(1);
}
// clean blank lines from end
matcher = Pattern.compile("((?:(?: *\\n)*(?: *\\S[^\\n]*\\n)+)+)(?: *\\n?)*").matcher(trimBegEnd);
if (matcher.matches()) {
trimBegEnd = matcher.group(1);
}
String out = "";
String[] lines = trimBegEnd.split("[\\r?\\n]");
matcher = Pattern.compile("( *).*").matcher(lines[0]);
if (matcher.matches()) {
int numSpaces = matcher.group(1).length();
Pattern spaceTrimmer = Pattern.compile(" {0," + numSpaces + "}(.*)");
for (int i = 0; i < lines.length; i++) {
matcher = spaceTrimmer.matcher(lines[i]);
if (matcher.matches()) {
out += matcher.group(1) + "\n";
} else {
throw new RuntimeException("How can this not match? pat=\"" + spaceTrimmer.pattern() + "\" |"
+ lines[i] + "|");
}
}
} else {
throw new RuntimeException("Didn't match:" + lines[0] + "|");
}
return out;
}
protected String script;
protected Element config;
protected String scriptType;;
protected ScriptEngine engine;
protected static ScriptEngineManager factory = new ScriptEngineManager();
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AbstractScriptSubsetter.class);
}