8000 Merge pull request #18 from scijava/input-providers · scijava/batch-processor@48c5b38 · GitHub
[go: up one dir, main page]

Skip to content
Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 48c5b38

Browse files
authored
Merge pull request #18 from scijava/input-providers
Add input provider plugins
2 parents 14d5b22 + c503a13 commit 48c5b38

File tree

9 files changed

+247
-20
lines changed

9 files changed

+247
-20
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</parent>
1111

1212
<artifactId>batch-processor</artifactId>
13-
<version>0.1.4-SNAPSHOT</version>
13+
<version>0.2.0-SNAPSHOT</version>
1414

1515
<name>Batch Processor</name>
1616
<description>A Batch Processor for SciJava Modules and Scripts</description>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ public class BatchModuleSearchActionFactory implements SearchActionFactory {
2222
@Override
2323
public boolean supports(final SearchResult result) {
2424
return (result instanceof ModuleSearchResult)
25-
&& batchService.supports(((ModuleSearchResult) result).info());
25+
&& batchService.supportsModule(((ModuleSearchResult) result).info());
2626
}
2727

2828
@Override
2929
public SearchAction create(final SearchResult result) {
30-
return new DefaultSearchAction("Batch", true, () -> {
30+
return new DefaultSearchAction("Batch", () -> {
3131
batchService.run(((ModuleSearchResult) result).info());
3232
});
3333
}

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,34 @@
44
import java.util.stream.Collectors;
55
import java.util.stream.StreamSupport;
66

7+
import org.scijava.batch.input.BatchInput;
8+
import org.scijava.batch.input.BatchInputProvider;
9+
import org.scijava.module.Module;
710
import org.scijava.module.ModuleInfo;
811
import org.scijava.module.ModuleItem;
12+
import org.scijava.plugin.HandlerService;
913
import org.scijava.service.SciJavaService;
1014

11-
public interface BatchService extends SciJavaService {
15+
public interface BatchService extends HandlerService<BatchInput, BatchInputProvider<?>>, SciJavaService {
1216
/**
1317
* Returns true if {@code moduleInfo} has at least one input item whose type
1418
* is supported by this service
1519
*/
16-
default public boolean supports(ModuleInfo moduleInfo) {
20+
default public boolean supportsModule(ModuleInfo moduleInfo) {
1721
for (ModuleItem<?> input : moduleInfo.inputs()) {
18-
if (supports(input.getType()))
22+
if (supportsItem(input))
1923
return true;
2024
}
2125
return false;
2226
}
27+
28+
//default public getHandler(ModuleItem)
2329

2430
/**
2531
* Returns true if {@code type} can be populated with batch inputs provided
2632
* by this service
2733
*/
28-
public boolean supports(Class<?> type);
34+
public boolean supportsItem(ModuleItem<?> moduleItem);
2935

3036
/**
3137
* Run the module described by {@link ModuleInfo} in batch.
@@ -38,7 +44,14 @@ default public boolean supports(ModuleInfo moduleInfo) {
3844
*/
3945
default public List<ModuleItem<?>> batchableInputs(ModuleInfo moduleInfo) {
4046
return StreamSupport.stream(moduleInfo.inputs().spliterator(), false)
41-
.filter(item -> supports(item.getType()))
47+
.filter(item -> supportsItem(item))
4248
.collect(Collectors.toList());
4349
}
50+
51+
/**
52+
* Fill a provided ModuleItem with a given input object
53+
* @param <I>
54+
*/
55+
public <I> void fillInput(Module module, ModuleItem<?> moduleItem, I inputObject);
56+
4457
}

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

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,48 @@
44
import java.util.HashMap;
55

66
import org.scijava.Priority;
7+
import org.scijava.batch.input.BatchInput;
8+
import org.scijava.batch.input.BatchInputProvider;
79
import org.scijava.command.CommandService;
810
import org.scijava.log.LogService;
11+
import org.scijava.module.Module;
912
import org.scijava.module.ModuleInfo;
13+
import org.scijava.module.ModuleItem;
14+
import org.scijava.plugin.AbstractHandlerService;
1015
import org.scijava.plugin.Parameter;
1116
import org.scijava.plugin.Plugin;
12-
import org.scijava.service.AbstractService;
1317
import org.scijava.service.Service;
1418

1519
@Plugin(type = Service.class, priority = Priority.LOW)
16-
public final class FileBatchService extends AbstractService implements
17-
BatchService {
20+
public final class FileBatchService extends AbstractHandlerService<BatchInput, BatchInputProvider<?>> implements BatchService {
1821

1922
@Parameter
2023
private LogService log;
21-
24+
2225
@Parameter
2326
private CommandService commandService;
2427

2528
/**
2629
* Returns true if {@code type} is a {@link File}.
2730
*/
2831
@Override
29-
public boolean supports(Class<?> type) {
30-
return type.isAssignableFrom(File.class);
32+
public boolean supportsItem(ModuleItem<?> moduleItem) {
33+
BatchInputProvider<?> handler = getHandler(new BatchInput(File.class, moduleItem));
34+
if (handler == null) {
35+
return false;
36+
}
37+
return handler.canProvide(moduleItem);
38+
}
39+
40+
@SuppressWarnings("unchecked")
41+
@Override
42+
public <I> void fillInput(Module module, ModuleItem<?> moduleItem, I inputObject) {
43+
BatchInputProvider<File> handler = (BatchInputProvider<File>) getHandler(new BatchInput(File.class, moduleItem));
44+
if (handler == null) {
45+
log.error("No handler found for input: " + moduleItem.getName());
46+
return;
47+
}
48+
handler.populateInput(module, moduleItem, (File) inputObject);
3149
}
3250

3351
@Override
@@ -37,10 +55,30 @@ public void run(ModuleInfo moduleInfo) {
3755
log.error("No compatible inputs (of type File) found.");
3856
return;
3957
}
58+
59+
// 1) get input ModuleItems
60+
// 2) choose ModuleItem
61+
// 3) get suitable BatchInputProvider
62+
// 4) get Iterator for ModuleItem
63+
64+
//for (getHandler(new BatchInput(File.class, moduleItem)).iterate(fileList)) {
65+
//}
66+
4067
// Call ModuleBatchProcessor with input moduleInfo
4168
HashMap<String, Object> inputMap = new HashMap<>();
4269
inputMap.put("moduleInfo", moduleInfo);
4370
commandService.run(ModuleBatchProcessor.class, true, inputMap);
4471
}
4572

73+
@SuppressWarnings({ "unchecked", "rawtypes" })
74+
@Override
75+
public Class<BatchInputProvider<?>> getPluginType() {
76+
return (Class) BatchInputProvider.class;
77+
}
78+
79+
@Override
80+
public Class<BatchInput> getType() {
81+
return BatchInput.class;
82+
}
83+
4684
}

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import org.scijava.widget.FileWidget;
2828

2929
@Plugin(type = Command.class, label = "Choose batch processing parameters", initializer = "initInputChoice")
30-
public class ModuleBatchProcessor extends DynamicCommand {
30+
public class ModuleBatchProcessor<T> extends DynamicCommand {
3131
@Parameter
3232
private ModuleService moduleService;
3333

@@ -66,6 +66,8 @@ protected void initInputChoice() {
6666
} else if (compatibleInputs.size() > 1) {
6767
choiceInput.setChoices(compatibleInputs.stream()
6868
.map(ModuleItem::getName).collect(Collectors.toList()));
69+
} else {
70+
log.error("No compatible inputs found. Unable to initialize input choice.");
6971
}
7072
}
7173

@@ -74,7 +76,7 @@ protected void initInputChoice() {
7476
@Override
7577
public void run() {
7678
// mark inputChoice as resolved, then harvest script parameters (i.e. run)
77-
ModuleItem<File> fileInput = moduleInfo.getInput(inputChoice, File.class);
79+
ModuleItem<?> inputModuleItem = moduleInfo.getInput(inputChoice);
7880
// TODO check if conversion needed?
7981
Module scriptModule = moduleService.createModule(moduleInfo);
8082
scriptModule.resolveInput(inputChoice);
@@ -89,8 +91,8 @@ public void run() {
8991
scriptModule.resolveOutput(outputKey);
9092
}
9193

92-
for (File file: inputFileList) {
93-
if(!processFile(scriptModule, fileInput, file)) {
94+
for (File file : inputFileList) {
95+
if(!processFile(scriptModule, inputModuleItem, file)) {
9496
log.warn("Terminating batch process.");
9597
break; // end for loop
9698
}
@@ -105,8 +107,9 @@ public void run() {
105107
// -- Helper methods --
106108

107109
@SuppressWarnings("unchecked")
108-
private boolean processFile(Module module, ModuleItem<File> fileInput, File file) {
109-
fileInput.setValue(module, file);
110+
private boolean processFile(Module module, ModuleItem<?> inputModuleItem, File file) {
111+
batchService.fillInput(module, inputModuleItem, file);
112+
//fileInput.setValue(module, file);
110113
outputTable.appendRow(file.getName());
111114

112115
Future<Module> instance = moduleService.run(module, true);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.scijava.batch.input;
2+
3+
import java.lang.reflect.Type;
4+
5+
import org.scijava.module.ModuleItem;
6+
7+
/**
8+
* Currency for use with {@link BatchInputProvider} methods
9+
*
10+
*
11+
*
12+
* @author Jan Eglinger
13+
*
14+
*/
15+
public class BatchInput {
16+
private final Type srcType;
17+
private final ModuleItem<?> destItem;
18+
19+
public BatchInput(final Class<?> srcClass, final ModuleItem<?> destItem) {
20+
this.srcType = srcClass;
21+
this.destItem = destItem;
22+
}
23+
24+
public BatchInput(final Type srcType, final ModuleItem<?> destItem) {
25+
this.srcType = srcType;
26+
this.destItem = destItem;
27+
}
28+
29+
public Type sourceType() {
30+
return srcType;
31+
}
32+
33+
public ModuleItem<?> moduleItem() {
34+
return destItem;
35+
}
36+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
package org.scijava.batch.input;
3+
4+
import org.scijava.module.Module;
5+
import org.scijava.module.ModuleItem;
6+
import org.scijava.plugin.HandlerPlugin;
7+
8+
public interface BatchInputProvider<I> extends HandlerPlugin<BatchInput> {
9+
10+
@Override
11+
default public Class<BatchInput> getType() {
12+
return BatchInput.class;
13+
}
14+
15+
/**
16+
* Check if a given {@code ModuleItem} can be populated by this input provider.
17+
* Implementations should make sure to not only match the type of objects, but
18+
* also respect possible widget style settings, such as files, directories,
19+
* image files only, etc.
20+
*
21+
* @param moduleItem
22+
* the input item that needs to be populated
23+
* @return true if this input provider can provide suitable objects
24+
*/
25+
public boolean canProvide(ModuleItem<?> moduleItem);
26+
27+
public void populateInput(Module module, ModuleItem<?> moduleItem, I inputObject);
28+
29+
public String getTargetWidgetStyle(ModuleItem<?> moduleItem);
30+
31+
// public Iterable<O> iterate(Collection<I> fileList);
32+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
package org.scijava.batch.input;
3+
4+
import java.io.File;
5+
import java.util.ArrayList;
6+
import java.util.Arrays;
7+
8+
import org.scijava.module.Module;
9+
import org.scijava.module.ModuleItem;
10+
import org.scijava.plugin.AbstractHandlerPlugin;
11+
import org.scijava.plugin.Plugin;
12+
import org.scijava.widget.FileListWidget;
13+
import org.scijava.widget.FileWidget;
14+
15+
@Plugin(type = BatchInputProvider.class)
16+
public class FileBatchInputProvider extends AbstractHandlerPlugin<BatchInput> implements
17+
BatchInputProvider<File>
18+
{
19+
@Override
20+
public boolean supports(BatchInput input) {
21+
return canProvide(input.moduleItem());
22+
}
23+
24+
@Override
25+
public boolean canProvide(ModuleItem<?> item) {
26+
// we can't provide inputs for saving files
27+
return item.getType() == File.class && !hasStyle(item, FileWidget.SAVE_STYLE);
28+
}
29+
30+
@SuppressWarnings("unchecked")
31+
@Override
32+
public void populateInput(Module module, ModuleItem<?> moduleItem, File inputObject) {
33+
((ModuleItem<File>)moduleItem).setValue(module, inputObject);
34+
}
35+
36+
@Override
37+
public String getTargetWidgetStyle(ModuleItem<?> item) {
38+
ArrayList<String> targetStyles = new ArrayList<>();
39+
40+
if (hasStyle(item, FileWidget.DIRECTORY_STYLE)) {
41+
targetStyles.add(FileListWidget.DIRECTORIES_ONLY);
42+
} else {
43+
targetStyles.add(FileListWidget.FILES_ONLY);
44+
}
45+
46+
// extensions?
47+
String widgetStyle = item.getWidgetStyle();
48+
if (widgetStyle != null) {
49+
String[] styles = widgetStyle.trim().split("\\s*,\\s*");
50+
for (String s : styles) {
51+
if (s.startsWith("extensions")) { // TODO: use new constant from FileListWidget
52+
targetStyles.add(s);
53+
}
54+
}
55+
}
56+
return String.join(",", targetStyles);
57+
}
58+
59+
private boolean hasStyle(ModuleItem<?> item, String style) {
60+
String widgetStyle = item.getWidgetStyle();
61+
if (widgetStyle == null) return false;
62+
return Arrays.asList(widgetStyle.trim().split("\\s*,\\s*"))
63+
.contains(style);
64+
}
65+
}

0 commit comments

Comments
 (0)
0