Skip to content

Commit 234a190

Browse files
authored
Merge pull request #121 from scijava/scijava-ops-legacy/openv-utils
Add utilities for OpEnvironment injection
2 parents cac4104 + d0b1183 commit 234a190

File tree

8 files changed

+266
-9
lines changed

8 files changed

+266
-9
lines changed

docs/ops/doc/ScriptingInImageJ2.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ Using SciJava Ops and ImageJ Ops2 within scripts provide the most powerful aspec
44

55
## Obtaining an OpEnvironment
66

7-
To run Ops, scripts must first create an `OpEnvironment`. The following line will create a new `OpEnvironment` containing all Ops available in the environment:
7+
To run Ops, scripts require an `OpEnvironment`. The easiest way to obtain an `OpEnvironment` with all available Ops is to declare an `OpEnvironment` as a script parameter:
88

99
```text
10-
import org.scijava.ops.api.OpEnvironment
11-
ops = OpEnvironment.getEnvironment()
10+
#@ OpEnvironment ops
1211
```
1312

1413
## Obtaining inputs
@@ -35,14 +34,11 @@ out = ops.op("filter.gauss").arity2().input(imgInput, new Double(3.0)).apply()
3534
The below script can be pasted into the Script Editor. **Ensure that the Script Editor is configured to run a Groovy script**.
3635

3736
```text
37+
#@ OpEnvironment ops
3838
#@ ThreadService ts
3939
#@ Img imgInput
4040
#@output Img out
4141
42-
// Obtain an OpEnvironment
43-
import org.scijava.ops.api.OpEnvironment
44-
ops = OpEnvironment.getEnvironment()
45-
4642
// Call some Ops!
4743
out = ops.op("filter.gauss").arity2().input(imgInput, new Double(3.0)).apply()
4844
```

scijava-ops-legacy/pom.xml

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,36 @@
9191

9292
<!-- NB: Deploy releases to the SciJava Maven repository. -->
9393
<releaseProfiles>sign,deploy-to-scijava</releaseProfiles>
94+
95+
<scijava-common.version>2.98.0</scijava-common.version>
9496
</properties>
97+
<build>
98+
<plugins>
99+
<plugin>
100+
<artifactId>maven-compiler-plugin</artifactId>
101+
<configuration>
102+
<annotationProcessorPaths>
103+
<path>
104+
<groupId>org.scijava</groupId>
105+
<artifactId>scijava-ops-indexer</artifactId>
106+
<version>${project.version}</version>
107+
</path>
108+
<path>
109+
<groupId>org.scijava</groupId>
110+
<artifactId>scijava-common</artifactId>
111+
<version>${scijava-common.version}</version>
112+
</path>
113+
</annotationProcessorPaths>
114+
<fork>true</fork>
115+
<showWarnings>true</showWarnings>
116+
<compilerArgs>
117+
<arg>-Aparse.ops="${scijava.parse.ops}"</arg>
118+
<arg>-Aop.version="${project.version}"</arg>
119+
</compilerArgs>
120+
</configuration>
121+
</plugin>
122+
</plugins>
123+
</build>
95124

96125
<repositories>
97126
<repository>
@@ -112,6 +141,10 @@
112141
<artifactId>scijava-collections</artifactId>
113142
<version>${project.version}</version>
114143
</dependency>
144+
<dependency>
145+
<groupId>org.scijava</groupId>
146+
<artifactId>scijava-common</artifactId>
147+
</dependency>
115148
<dependency>
116149
<groupId>org.scijava</groupId>
117150
<artifactId>scijava-priority</artifactId>
@@ -156,5 +189,23 @@
156189
<version>${project.version}</version>
157190
<scope>test</scope>
158191
</dependency>
159-
</dependencies>
192+
<dependency>
193+
<groupId>org.scijava</groupId>
194+
<artifactId>scijava-ops-api</artifactId>
195+
<version>${project.version}</version>
196+
<scope>compile</scope>
197+
</dependency>
198+
<dependency>
199+
<groupId>org.scijava</groupId>
200+
<artifactId>scijava-ops-engine</artifactId>
201+
<version>${project.version}</version>
202+
<scope>test</scope>
203+
</dependency>
204+
<dependency>
205+
<groupId>org.scijava</groupId>
206+
<artifactId>scijava-progress</artifactId>
207+
<version>0-SNAPSHOT</version>
208+
<scope>compile</scope>
209+
</dependency>
210+
</dependencies>
160211
</project>

scijava-ops-legacy/src/main/java/module-info.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@
2626
* POSSIBILITY OF SUCH DAMAGE.
2727
* #L%
2828
*/
29-
module org.scijava.legacy {
29+
open module org.scijava.legacy {
3030

3131
requires net.imagej;
32+
requires org.scijava;
3233
requires org.scijava.types;
3334
requires org.scijava.priority;
35+
requires org.scijava.ops.api;
3436

3537
provides org.scijava.types.TypeExtractor with org.scijava.legacy.types.DatasetTypeExtractor;
3638
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
package org.scijava.legacy.module.process;
3+
4+
import org.scijava.Priority;
5+
import org.scijava.legacy.service.OpEnvironmentService;
6+
import org.scijava.module.Module;
7+
import org.scijava.module.ModuleItem;
8+
import org.scijava.module.process.AbstractPreprocessorPlugin;
9+
import org.scijava.module.process.PreprocessorPlugin;
10+
import org.scijava.ops.api.OpEnvironment;
11+
import org.scijava.plugin.Parameter;
12+
import org.scijava.plugin.Plugin;
13+
14+
/**
15+
* A {@link PreprocessorPlugin} used to inject an {@link OpEnvironment}, created
16+
* by the {@link OpEnvironmentService}, into {@link Module}s.
17+
*
18+
* @author Gabriel Selzer
19+
*/
20+
@Plugin(type = PreprocessorPlugin.class, priority = Priority.HIGH)
21+
public class OpEnvironmentPreprocessorPlugin extends
22+
AbstractPreprocessorPlugin
23+
{
24+
25+
@Parameter
26+
private OpEnvironmentService opEnvironmentService;
27+
28+
@Override
29+
public void process(Module module) {
30+
for (final ModuleItem<?> input : module.getInfo().inputs()) {
31+
if (!input.isAutoFill()) continue;
32+
if (module.isInputResolved(input.getName())) continue;
33+
final Class<?> type = input.getType();
34+
if (OpEnvironment.class.equals(type)) {
35+
@SuppressWarnings("unchecked")
36+
final ModuleItem<OpEnvironment> envInput =
37+
(ModuleItem<OpEnvironment>) input;
38+
envInput.setValue(module, opEnvironmentService.env());
39+
module.resolveInput(input.getName());
40+
}
41+
}
42+
}
43+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
package org.scijava.legacy.service;
3+
4+
import org.scijava.ops.api.OpEnvironment;
5+
import org.scijava.plugin.Attr;
6+
import org.scijava.plugin.Parameter;
7+
import org.scijava.plugin.Plugin;
8+
import org.scijava.script.ScriptService;
9+
import org.scijava.service.AbstractService;
10+
import org.scijava.service.Service;
11+
12+
/**
13+
* Default implementation of {@link OpEnvironmentService}
14+
*
15+
* @author Gabriel Selzer
16+
*/
17+
@Plugin(type = Service.class, attrs = { @Attr(name = "noAlias") })
18+
public class DefaultOpEnvironmentService extends AbstractService implements
19+
OpEnvironmentService
20+
{
21+
22+
@Parameter(required = false)
23+
private ScriptService scriptService;
24+
25+
private OpEnvironment env;
26+
27+
@Override
28+
public void initialize() {
29+
// Build the Op Environment
30+
env = OpEnvironment.build();
31+
32+
// Set up alias, if ScriptService available
33+
if (scriptService != null) {
34+
scriptService.addAlias(OpEnvironment.class);
35+
}
36+
}
37+
38+
@Override
39+
public OpEnvironment env() {
40+
return env;
41+
}
42+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
package org.scijava.legacy.service;
3+
4+
import org.scijava.ops.api.OpEnvironment;
5+
import org.scijava.service.SciJavaService;
6+
import org.scijava.service.Service;
7+
8+
/**
9+
* A SciJava {@link Service} that instantiates a single {@link OpEnvironment}.
10+
* The primary use case is in SciJava scripting, but within scripts this service
11+
* should not be used - instead, users should declare an {@link OpEnvironment}
12+
* parameter, which will be filled using a preprocessor plugin.
13+
*
14+
* @author Gabriel Selzer
15+
*/
16+
public interface OpEnvironmentService extends SciJavaService {
17+
18+
/**
19+
* Returns this Service's {@link OpEnvironment}.
20+
*
21+
* @return an {@link OpEnvironment}
22+
*/
23+
OpEnvironment env();
24+
25+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
package org.scijava.legacy.module.process;
3+
4+
import org.junit.jupiter.api.Test;
5+
import org.scijava.Context;
6+
import org.scijava.command.Command;
7+
import org.scijava.command.CommandService;
8+
import org.scijava.legacy.service.OpEnvironmentService;
9+
import org.scijava.ops.api.OpEnvironment;
10+
import org.scijava.plugin.Parameter;
11+
12+
import java.util.concurrent.ExecutionException;
13+
14+
/**
15+
* Tests the ability of {@link OpEnvironmentPreprocessorPlugin} to fill in
16+
* {@link OpEnvironment} module parameters.
17+
*
18+
* @author Gabriel Selzer
19+
*/
20+
public class OpEnvironmentPreprocessorTest {
21+
22+
@Test
23+
public void testOpEnvironmentPreprocessor() throws ExecutionException,
24+
InterruptedException
25+
{
26+
var context = new Context(CommandService.class, OpEnvironmentService.class);
27+
var commandService = context.service(CommandService.class);
28+
commandService.run(CommandWithOpEnvironment.class, true).get();
29+
context.dispose();
30+
}
31+
32+
public static class CommandWithOpEnvironment implements Command {
33+
34+
@Parameter
35+
public OpEnvironment env;
36+
37+
@Override
38+
public void run() {
39+
// Fails the test if the OpEnvironment was not injected
40+
if (env == null) {
41+
throw new IllegalArgumentException(
42+
"OpEnvironment not properly injected!");
43+
}
44+
}
45+
}
46+
47+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
package org.scijava.legacy.service;
3+
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.Test;
6+
import org.scijava.Context;
7+
import org.scijava.ops.api.OpEnvironment;
8+
import org.scijava.script.ScriptService;
9+
10+
/**
11+
* Tests {@link OpEnvironmentService} API.
12+
*
13+
* @author Gabriel Selzer
14+
*/
15+
public class OpEnvironmentServiceTest {
16+
17+
/**
18+
* Tests that an {@link OpEnvironmentService} produces an
19+
* {@link OpEnvironment} with some Ops in it.
20+
*/
21+
@Test
22+
public void testOpEnvironmentService() {
23+
Context ctx = new Context(OpEnvironmentService.class);
24+
OpEnvironmentService ops = ctx.getService(OpEnvironmentService.class);
25+
Double result = ops.env().binary("math.add") //
26+
.input(2., 3.) //
27+
.outType(Double.class) //
28+
.apply();
29+
Assertions.assertEquals(5., result);
30+
ctx.dispose();
31+
}
32+
33+
/**
34+
* Test that when a {@link ScriptService} is present, the "OpEnvironment"
35+
* alias points to {@link OpEnvironment}.
36+
*/
37+
@Test
38+
public void testOpEnvironmentServiceAliases() {
39+
Context ctx = new Context(OpEnvironmentService.class, ScriptService.class);
40+
ScriptService script = ctx.getService(ScriptService.class);
41+
// Assert the correct alias for OpEnvironment
42+
Assertions.assertEquals( //
43+
OpEnvironment.class, //
44+
script.getAliases().get("OpEnvironment") //
45+
);
46+
// Assert no alias for OpEnvironmentService
47+
Assertions.assertNull(script.getAliases().get("OpEnvironmentService"));
48+
ctx.dispose();
49+
}
50+
51+
}

0 commit comments

Comments
 (0)