Skip to content

Commit 345b8e0

Browse files
committed
Add script_templates and ensure output values can be extracted by
scripting framework Capturing the output of Scala script for the scripting framework turned out to be tricky. Values (or variables) computed by Scala script engine are not added to bindings of CompiledScript AFAICT. Only way to extract them is to eval the variable and capture the return.
1 parent b522c29 commit 345b8e0

File tree

5 files changed

+115
-2
lines changed

5 files changed

+115
-2
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* #%L
3+
* JSR-223-compliant Scala scripting language plugin.
4+
* %%
5+
* Copyright (C) 2013 - 2016 Board of Regents of the University of
6+
* Wisconsin-Madison.
7+
* %%
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
* 2. Redistributions in binary form must reproduce the above copyright notice,
14+
* this list of conditions and the following disclaimer in the documentation
15+
* and/or other materials provided with the distribution.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
21+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
* #L%
29+
*/
30+
31+
package org.scijava.plugins.scripting.scala;
32+
33+
import javax.script.ScriptEngine;
34+
import javax.script.ScriptException;
35+
36+
import org.scijava.script.AdaptedScriptEngine;
37+
38+
/**
39+
* Scala interpreter
40+
*
41+
* @author Keith Schulze
42+
* @see ScriptEngine
43+
*/
44+
public class ScalaScriptEngine extends AdaptedScriptEngine {
45+
46+
public ScalaScriptEngine(ScriptEngine engine) {
47+
super(engine);
48+
}
49+
50+
@Override
51+
public Object get(String key) {
52+
// First try to get value from bindings
53+
Object value = super.get(key);
54+
55+
// NB: Extracting values from Scala Script Engine are a little tricky.
56+
// Values (variables) initialised or computed in the script are
57+
// not added to the bindings of the CompiledScript AFAICT. Therefore
58+
// the only way to extract them is to evaluate the variable and
59+
// capture the return. If it evaluates to null or throws a
60+
// a ScriptException, we simply return null.
61+
if (value == null) try {
62+
value = super.eval(key);
63+
} catch (ScriptException ignored) {
64+
// HACK: Explicitly ignore ScriptException, which arises if
65+
// key is not found. This feels bad because it fails silently
66+
// for the user, but it mimics behaviour in other script langs.
67+
}
68+
69+
return value;
70+
}
71+
}

src/main/java/org/scijava/plugins/scripting/scala/ScalaScriptLanguage.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ public ScriptEngine getScriptEngine() {
7070
final Settings settings = new Settings();
7171
settings.classpath().value_$eq(getClasspath());
7272

73-
return Scripted.apply(new Scripted.Factory(), settings,
74-
new NewLinePrintWriter(new ConsoleWriter(), true));
73+
Scripted eng = Scripted.apply(new Scripted.Factory(), settings,
74+
new NewLinePrintWriter(new ConsoleWriter(), true));
75+
76+
return new ScalaScriptEngine(eng);
7577
}
7678

7779
/** Retrieves the current classpath as a string. */
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// @Dataset inputImg
2+
// @OpService ops
3+
// @OUTPUT Dataset(label="Blurred") blurredImg
4+
5+
// A simple Scala script that blurs an input image with
6+
// a Gaussian filter. Note that you must have an image
7+
// open to run this script.
8+
// It is the duty of the scripting framework to bind
9+
// the input image and then display the blurred output
10+
// image. It also binds the ImageJ OpService for filtering.
11+
12+
import net.imagej.ops.OpService
13+
import net.imglib2.img.Img
14+
import net.imglib2.`type`.numeric.RealType
15+
16+
// Scala is a compiled language with a very strict/powerful
17+
// type system. We need to cast any parameters that are bound
18+
// at runtime to their known type otherwise the Scala compiler
19+
// will throw Type errors.
20+
21+
// Dataset extends Img[RealType[_]]. We cast directly to
22+
// Img[RealType[_]] to narrow the underlying pixel type,
23+
// which is required for the Gauss filter.
24+
val img = inputImg.asInstanceOf[Img[T] forSome {type T <: RealType[T]}]
25+
26+
val blurredImg = ops.asInstanceOf[OpService].filter().gauss(img, 2)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @String(label="Please enter your name",description="Name field") name
2+
// @OUTPUT String greeting
3+
4+
// A Scala script with parameters
5+
// It is the duty of the scripting framework to harvest
6+
// the 'name' parameter from the user, and then display
7+
// the 'greeting' output parameter, based on it's type.
8+
9+
val greeting = s"Hello, ${name}!"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// A very simple Scala script.
2+
// It is the duty of the scripting framework to display
3+
// the script's return value, based on its type.
4+
5+
"Hello, World!"

0 commit comments

Comments
 (0)