Skip to content

Instantly share code, notes, and snippets.

@mpkocher
Last active August 29, 2015 14:05
Show Gist options
  • Save mpkocher/fd1bc03328bd0ac2dab3 to your computer and use it in GitHub Desktop.
Save mpkocher/fd1bc03328bd0ac2dab3 to your computer and use it in GitHub Desktop.
Nashorn Experiments Scala + JS (Requires Oracle JDK1.8 )
function test(){
/** Task Authors should write unittest-esque tests to validate
* the tasks are well-formed
*
*/
return(true);
}
function exampleTask(taskId) {
var taskClass = Java.type("com.github.mpkocher.Task");
var t = new taskClass(taskId, "Task Description");
return(t);
}
function toCmd(inputFiles, outputFiles, specials, opts, nproc) {
/**
* This is just to experiment with passing java objects to js
*
* In the real system, a Task would implement the abstract toCmd method
* which has the signature (inputFiles, outputFiles, specials, opts, nproc)
*
* Adds two numbers
* @param {Array} inputFiles
* @param {Array} outputFiles
* @param {Array} specials (e.g, $tmpdir, $tmpfile
* @param {Object} opts (HashMap of k->v of resolved option values)
* @param {Number} nproc the number of processors/slots to allocate
* @return {String} cmd
*/
print("Paths in javascript:");
print(inputFiles);
print(Object.prototype.toString.call(inputFiles));
print(inputFiles.getClass());
print(opts);
var cmd = "my_exe";
cmd += " --optionA=12 --optionB=stuff ";
cmd += " --tmpdir=" + specials['1'] + "--tmpfile=" + specials['0'];
cmd += " --output=" + outputFiles['1'] + " " + outputFiles['0'];
cmd += " " + inputFiles['0'] + ' --reference=' + inputFiles['1'];
print(cmd);
return(cmd);
}
function registeredTasks() {
/*
These are the main public methods/funcs that are core the API
The task author should also implement a 'test' function
The scala code or the javascript UI code expects these funcs to be implemented.
*/
var taskClass = Java.type("com.github.mpkocher.Task");
var t1 = new taskClass("task1", "task one description");
var t2 = new taskClass('task2', "task two description");
return([t1, t2]);
}
> run
[info] Running com.github.mpkocher.Program
Number of factory
3
Oracle Nashorn
ECMAScript
Scala Interpreter
Scala
AppleScriptEngine
AppleScript
jdk.nashorn.api.scripting.NashornScriptEngine@208180ea
Hello Hello From Javascript
12
Paths in javascript:
[/path/to/input.fofn, /path/to/reference.fasta]
[object java.util.ArrayList]
class java.util.ArrayList
{task_option_id2=value2, task_option_id1=value1}
my_exe --optionA=12 --optionB=stuff --tmpdir=/path/to/tmpdir1--tmpfile=/path/to/tmp.file.txt --output=/path/to/file2.fasta /path/to/file.fofn /path/to/input.fofn --reference=/path/to/reference.fasta
Command
my_exe --optionA=12 --optionB=stuff --tmpdir=/path/to/tmpdir1--tmpfile=/path/to/tmp.file.txt --output=/path/to/file2.fasta /path/to/file.fofn /path/to/input.fofn --reference=/path/to/reference.fasta
Task id: taskId.1234
description: Task Description
Load tests
true
[object Array]
Task id: taskId1
description: My Task 1 description
Exiting main.
[success] Total time: 0 s, completed Sep 1, 2014 9:23:57 PM
package com.github.mpkocher
import java.io.IOException
import java.nio.charset.Charset
import java.nio.file.Files
import java.nio.file.Paths
import java.util
import java.util.List
import java.util.ArrayList
import javax.script.ScriptEngineFactory
import javax.script.ScriptEngineManager
import javax.script.ScriptEngine
import javax.script.ScriptException
import java.io.FileReader
import com.github.mpkocher.Task
object Program extends App {
override def main(args: Array[String]): Unit = {
// create ScriptEngineManager
// http://stackoverflow.com/questions/23567500/how-to-use-scriptengine-in-scalatest/23575337#23575337
// sbt has an odd value for the class path
val manager: ScriptEngineManager = new ScriptEngineManager(getClass.getClassLoader)
// Print all the scriptengines that installed
val factoryList: util.List[ScriptEngineFactory] = manager.getEngineFactories
println("Number of factory")
println(factoryList.size())
// This automatically converts types for java types
import scala.collection.JavaConversions._
for (factory <- factoryList) {
println(factory.getEngineName)
println(factory.getLanguageName)
}
val engine = manager.getEngineByName("nashorn")
println(engine)
engine.eval(new FileReader("/Users/mkocher/scratch/js-scriptengine-example/src/main/resources/example_tasks.js"))
val invocable = engine.asInstanceOf[javax.script.Invocable]
// val outputFiles = Seq("/path/to/file.fofn", "/path/to/file2.fasta")
// Not sure why this doesn't work
// Have to use direct java objects to get objects to get passed directly
// otherwise a [object scala.collection.immutable.$colon$colon]
// class scala.collection.immutable.$colon$colon
// is passed to the js function
var inputFiles = new java.util.ArrayList[String]()
inputFiles.append("/path/to/input.fofn")
inputFiles.append("/path/to/reference.fasta")
var outputFiles = new java.util.ArrayList[String]()
outputFiles.append("/path/to/file.fofn")
outputFiles.append("/path/to/file2.fasta")
// These should be the resolved options
var opts = new java.util.HashMap[String, String]
opts.put("task_option_id1", "value1")
opts.put("task_option_id2", "value2")
// Assume DI specials is ['$tmpfile', '$tmpdir']
var specials = new java.util.ArrayList[String]()
specials.append("/path/to/tmp.file.txt")
specials.append("/path/to/tmpdir1")
val nproc = java.lang.Integer.parseInt("12")
println(nproc)
// This is the fundamental signature of calling a task.toCmd func
// Passing nproc as an int won't automatically get converted for some reason.
val cmd = invocable.invokeFunction("toCmd", inputFiles, outputFiles, specials, opts, "12")
println("Command")
println(cmd)
// Raw Java task creation
val t = new Task("taskId1", "My Task 1 description")
// Access an instance of java class defined in javascript
val jsTask = invocable.invokeFunction("exampleTask", "taskId.1234")
println(jsTask)
// Call test Method. The task author should implement a unittest-esque method in javascript to make sure
// their tasks are well defined
val runTests = invocable.invokeFunction("test", Nil)
val isValid = runTests.asInstanceOf[Boolean]
println("Load tests ")
println(isValid)
// Load all registered tasks. This should return a list of Task instances
val ts = invocable.invokeFunction("registeredTasks", Nil)
println(ts)
// Not sure why this doesn't work.
//val tasks = ts.asInstanceOf[Seq[Task]]
//println(tasks)
println(t)
println("Exiting main.")
}
}
package com.github.mpkocher;
import java.util.ArrayList;
public class Task {
// Making this as minimal as possible to get the point across.
public String taskId;
public String description;
public Task(String ataskId, String adescription) {
taskId = ataskId;
description = adescription;
}
@Override
public String toString() {
return "Task id: " + taskId+ " \ndescription: " + description + "\n\n";
}
// Need an abstract method for the toCmd(ArrayList<String>) -> String
public String toCmd(ArrayList<String> paths) {
return "my exe.sh";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment