package com.sleazyweasel.applescriptifier;
import javax.script.*;
import java.util.Arrays;
import java.util.List;
public class ScriptEngineAppleScriptTemplate implements AppleScriptTemplate {
private ScriptEngine getEngine() {
return new ScriptEngineManager().getEngineByName("AppleScript");
}
private <T> T execute(ScriptEngine engine, CharSequence script) {
try {
return (T) engine.eval(script.toString(), engine.getContext());
} catch (ScriptException e) {
throw new AppleScriptException(e);
}
}
public <T> T execute(CharSequence script, String... args) {
ScriptEngine engine = getEngine();
if (args.length > 0) {
setArgs(Arrays.asList(args), engine);
return (T) execute(engine, script);
} else {
return (T) execute(engine, script);
}
}
public <T> T execute(Application applicationName, String... scriptLines) {
return (T) execute(getEngine(), applicationName, scriptLines);
}
@Override
public void executeBare(String... scriptLines) {
StringBuilder builder = new StringBuilder();
buildCommand(builder, scriptLines);
execute(builder);
}
private <T> T execute(ScriptEngine engine, Application applicationName, String... scriptLines) {
StringBuilder command = new StringBuilder("tell application \"").append(applicationName.name()).append("\"\n");
buildCommand(command, scriptLines);
command.append("end tell\n");
return (T) execute(engine, command);
}
private void buildCommand(StringBuilder command, String[] scriptLines) {
for (String scriptLine : scriptLines) {
command.append(scriptLine).append("\n");
}
}
private <T> T execute(ScriptEngine engine, Application applicationName, Bindings bindings, String... scriptLines) {
StringBuilder command = new StringBuilder("tell application ").append(applicationName.name()).append("\n");
buildCommand(command, scriptLines);
command.append("end tell\n");
return (T) execute(engine, command);
}
public <T> T execute(Application application, List<String> args, String... scriptLines) {
ScriptEngine engine = getEngine();
Bindings bindings = setArgs(args, engine);
return (T) execute(engine, application, bindings, scriptLines);
}
public boolean isRunning(Application application) {
String isAirfoilRunningScript = "tell application \"System Events\"\n" +
" set runningState to count (every process whose name is \"" + application.name() + "\")\n" +
"end tell\n";
Long numberOfProcesses = execute(isAirfoilRunningScript);
return numberOfProcesses != null && numberOfProcesses > 0;
}
public void startApplication(Application application) {
String startScript = "tell application \"" + application.name() + "\" to activate";
execute(startScript);
}
public boolean applicationExists(Application application) {
String query = "try\n" +
" tell application \"Finder\"\n" +
" return application file id \"" + application.identifier() + "\"\n" +
" end tell\n" +
"on error err_msg number err_num\n" +
" return null\n" +
"end try";
Object result = execute(query);
return result != null;
}
public void executeKeyStroke(Application application, String keyStroke) {
execute(application, "activate", "tell application \"System Events\" to keystroke \"" + keyStroke + "\"");
}
public void executeKeyStrokeWithCommandKey(Application application, String keyStroke) {
execute(application, "activate", "tell application \"System Events\" to keystroke \"" + keyStroke + "\" using command down");
}
public void executeKeyCode(Application application, int keyCode) {
execute(application, "activate", "tell application \"System Events\" to key code " + keyCode);
}
private Bindings setArgs(List<String> args, ScriptEngine engine) {
Bindings bindings = engine.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
bindings.put("javax_script_function", "dorun");
//todo support more than one arg!
bindings.put(ScriptEngine.ARGV, args.get(0));
return bindings;
}
}