Skip to content

Commit 1767d84

Browse files
authored
Merge pull request #10 from scijava/batch-service
Add BatchService and integrate into search bar
2 parents 6321eb8 + a0f8bd3 commit 1767d84

File tree

6 files changed

+171
-26
lines changed

6 files changed

+171
-26
lines changed

pom.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>org.scijava</groupId>
1010
<artifactId>pom-scijava</artifactId>
11-
<version>17.1.1</version>
11+
<version>18.0.0</version>
1212
<relativePath />
1313
</parent>
1414

@@ -100,17 +100,27 @@
100100
<artifactId>scijava-common</artifactId>
101101
</dependency>
102102
<dependency>
103+
<!-- TODO: remove this dependency when table support moved to SciJava -->
103104
<groupId>net.imagej</groupId>
104105
<artifactId>imagej</artifactId>
105106
</dependency>
106107
<dependency>
107108
<groupId>org.scijava</groupId>
108109
<artifactId>scijava-ui-swing</artifactId>
109110
</dependency>
111+
<dependency>
112+
<groupId>org.scijava</groupId>
113+
<artifactId>scijava-search</artifactId>
114+
</dependency>
110115
<dependency>
111116
<groupId>commons-io</groupId>
112117
<artifactId>commons-io</artifactId>
113118
<version>2.4</version>
114119
</dependency>
120+
<dependency>
121+
<groupId>junit</groupId>
122+
<artifactId>junit</artifactId>
123+
<scope>test</scope>
124+
</dependency>
115125
</dependencies>
116126
</project>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.scijava.batch;
2+
3+
import org.scijava.plugin.Parameter;
4+
import org.scijava.plugin.Plugin;
5+
import org.scijava.search.DefaultSearchAction;
6+
import org.scijava.search.SearchAction;
7+
import org.scijava.search.SearchActionFactory;
8+
import org.scijava.search.SearchResult;
9+
import org.scijava.search.module.ModuleSearchResult;
10+
11+
/**
12+
* Search action for executing a SciJava module in batch mode.
13+
*
14+
* @author Jan Eglinger
15+
*/
16+
@Plugin(type = SearchActionFactory.class)
17+
public class BatchModuleSearchActionFactory implements SearchActionFactory {
18+
19+
@Parameter
20+
private BatchService batchService;
21+
22+
@Override
23+
public boolean supports(final SearchResult result) {
24+
return (result instanceof ModuleSearchResult)
25+
&& batchService.supports(((ModuleSearchResult) result).info());
26+
}
27+
28+
@Override
29+
public SearchAction create(final SearchResult result) {
30+
return new DefaultSearchAction("Batch", true, () -> {
31+
batchService.run(((ModuleSearchResult) result).info());
32+
});
33+
}
34+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.scijava.batch;
2+
3+
import java.util.List;
4+
import java.util.stream.Collectors;
5+
import java.util.stream.StreamSupport;
6+
7+
import org.scijava.module.ModuleInfo;
8+
import org.scijava.module.ModuleItem;
9+
import org.scijava.service.SciJavaService;
10+
11+
public interface BatchService extends SciJavaService {
12+
/**
13+
* Returns true if {@code moduleInfo} has at least one input item whose type
14+
* is supported by this service
15+
*/
16+
default public boolean supports(ModuleInfo moduleInfo) {
17+
for (ModuleItem<?> input : moduleInfo.inputs()) {
18+
if (supports(input.getType()))
19+
return true;
20+
}
21+
return false;
22+
}
23+
24+
/**
25+
* Returns true if {@code type} can be populated with batch inputs provided
26+
* by this service
27+
*/
28+
public boolean supports(Class<?> type);
29+
30+
/**
31+
* Run the module described by {@link ModuleInfo} in batch.
32+
*/
33+
public void run(ModuleInfo moduleInfo);
34+
35+
/**
36+
* A collection of input {@link ModuleItem}s of the given {@link ModuleInfo}
37+
* that are supported (i.e. can be batch-processed) by this service
38+
*/
39+
default public List<ModuleItem<?>> batchableInputs(ModuleInfo moduleInfo) {
40+
return StreamSupport.stream(moduleInfo.inputs().spliterator(), false)
41+
.filter(item -> supports(item.getType()))
42+
.collect(Collectors.toList());
43+
}
44+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.scijava.batch;
2+
3+
import java.io.File;
4+
import java.util.HashMap;
5+
6+
import org.scijava.Priority;
7+
import org.scijava.command.CommandService;
8+
import org.scijava.module.ModuleInfo;
9+
import org.scijava.plugin.Parameter;
10+
import org.scijava.plugin.Plugin;
11+
import org.scijava.service.AbstractService;
12+
import org.scijava.service.Service;
13+
14+
@Plugin(type = Service.class, priority = Priority.LOW)
15+
public final class FileBatchService extends AbstractService implements
16+
BatchService {
17+
18+
@Parameter
19+
private CommandService commandService;
20+
21+
/**
22+
* Returns true if {@code type} is a {@link File}.
23+
*/
24+
@Override
25+
public boolean supports(Class<?> type) {
26+
return type.isAssignableFrom(File.class);
27+
}
28+
29+
@Override
30+
public void run(ModuleInfo moduleInfo) {
31+
// Call ModuleBatchProcessor with input moduleInfo
32+
HashMap<String, Object> inputMap = new HashMap<>();
33+
inputMap.put("moduleInfo", moduleInfo);
34+
commandService.run(ModuleBatchProcessor.class, true, inputMap);
35+
}
36+
37+
}

src/main/java/org/scijava/batch/ModuleBatchProcessor.java

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.Map.Entry;
88
import java.util.concurrent.ExecutionException;
99
import java.util.concurrent.Future;
10+
import java.util.stream.Collectors;
1011

1112
import net.imagej.table.Column;
1213
import net.imagej.table.DefaultGenericTable;
@@ -15,8 +16,7 @@
1516
import org.scijava.ItemIO;
1617
import org.scijava.command.Command;
1718
import org.scijava.command.DynamicCommand;
18-
import org.scijava.convert.ConvertService;
19-
import org.scijava.log.LogService;
19+
import org.scijava.log.Logger;
2020
import org.scijava.module.Module;
2121
import org.scijava.module.ModuleInfo;
2222
import org.scijava.module.ModuleItem;
@@ -29,17 +29,17 @@
2929
@Plugin(type = Command.class, label = "Choose batch processing parameters", initializer = "initInputChoice")
3030
public class ModuleBatchProcessor extends DynamicCommand {
3131
@Parameter
32-
private ModuleService modules;
32+
private ModuleService moduleService;
3333

3434
@Parameter
35-
private ConvertService convert;
36-
35+
private BatchService batchService;
36+
3737
@Parameter
38-
private LogService log;
39-
38+
private Logger log;
39+
4040
@Parameter
4141
private ModuleInfo moduleInfo; // to be provided at runtime!
42-
42+
4343
@Parameter(label = "Which input parameter to batch?", persist = false)
4444
private String inputChoice;
4545

@@ -57,23 +57,15 @@ public class ModuleBatchProcessor extends DynamicCommand {
5757

5858
protected void initInputChoice() {
5959
MutableModuleItem<String> choiceInput = getInfo().getMutableInput("inputChoice", String.class);
60-
// get compatible inputs from module
61-
ArrayList<String> compatibleInputs = new ArrayList<>();
62-
for (ModuleItem<?> input : moduleInfo.inputs()) {
63-
// TODO consider replacing by isAssignableFrom
64-
if (convert.supports(new File(""), input.getType())) {
65-
// if we can convert a File to the given input,
66-
// add it to the list of compatible inputs
67-
compatibleInputs.add(input.getName());
68-
}
69-
}
70-
// if only single input left, fill module input and resolve 'inputChoice'
60+
// Get compatible inputs for moduleInfo
61+
List<ModuleItem<?>> compatibleInputs = batchService
62+
.batchableInputs(moduleInfo);
7163
if (compatibleInputs.size() == 1) {
72-
choiceInput.setValue(this, compatibleInputs.get(0));
64+
choiceInput.setValue(this, compatibleInputs.get(0).getName());
7365
resolveInput("inputChoice");
74-
}
75-
else if (compatibleInputs.size() > 1) {
76-
choiceInput.setChoices(compatibleInputs);
66+
} else if (compatibleInputs.size() > 1) {
67+
choiceInput.setChoices(compatibleInputs.stream()
68+
.map(ModuleItem::getName).collect(Collectors.toList()));
7769
}
7870
}
7971

@@ -84,7 +76,7 @@ public void run() {
8476
// mark inputChoice as resolved, then harvest script parameters (i.e. run)
8577
ModuleItem<File> fileInput = moduleInfo.getInput(inputChoice, File.class);
8678
// TODO check if conversion needed?
87-
Module scriptModule = modules.createModule(moduleInfo);
79+
Module scriptModule = moduleService.createModule(moduleInfo);
8880
scriptModule.resolveInput(inputChoice);
8981

9082
/* Create output Table and mark all outputs as resolved */
@@ -117,7 +109,7 @@ private boolean processFile(Module module, ModuleItem<File> fileInput, File file
117109
fileInput.setValue(module, file);
118110
outputTable.appendRow(file.getName());
119111

120-
Future<Module> instance = modules.run(module, true);
112+
Future<Module> instance = moduleService.run(module, true);
121113
try {
122114
// run the script
123115
Map<String, Object> outputs = instance.get().getOutputs();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.scijava.batch;
2+
3+
import static org.junit.Assert.assertNotNull;
4+
5+
import org.junit.After;
6+
import org.junit.Test;
7+
import org.scijava.Context;
8+
9+
public class BatchServiceTest {
10+
11+
private Context context;
12+
13+
@After
14+
public void disposeContext() {
15+
if (context != null) {
16+
context.dispose();
17+
context = null;
18+
}
19+
}
20+
21+
@Test
22+
public void testContext() {
23+
context = new Context(BatchService.class);
24+
final BatchService batchService =
25+
context.getService(BatchService.class);
26+
assertNotNull(batchService);
27+
}
28+
}

0 commit comments

Comments
 (0)