Skip to content

Commit eeaa8eb

Browse files
committed
Merge branch 'resolve-outputs'
This branch adds a resolution mechanism for module outputs, for use during postprocessing. And the display postprocessor now flags displayed outputs as resolved. This paves the way for additional postprocessors which can handle outputs in alternative ways, similar to how various preprocessors are able to populate and resolve inputs in different ways.
2 parents bd51228 + a6bf3cf commit eeaa8eb

16 files changed

+118
-39
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>scijava-common</artifactId>
13-
<version>2.58.4-SNAPSHOT</version>
13+
<version>2.59.0-SNAPSHOT</version>
1414

1515
<name>SciJava Common</name>
1616
<description>SciJava Common is a shared library for SciJava software. It provides a plugin framework, with an extensible mechanism for service discovery, backed by its own annotation processor, so that plugins can be loaded dynamically. It is used by downstream projects in the SciJava ecosystem, such as ImageJ and SCIFIO.</description>

src/main/java/org/scijava/command/CommandModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ private void assignPresets() {
266266
for (final String name : presets.keySet()) {
267267
final Object value = presets.get(name);
268268
setInput(name, value);
269-
setResolved(name, true);
269+
resolveInput(name);
270270
}
271271
}
272272

src/main/java/org/scijava/display/ActiveDisplayPreprocessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public void process(final Module module) {
8282

8383
final String name = displayInput.getName();
8484
module.setInput(name, activeDisplay);
85-
module.setResolved(name, true);
85+
module.resolveInput(name);
8686
}
8787

8888
}

src/main/java/org/scijava/display/DisplayPostprocessor.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,11 @@ public void process(final Module module) {
6868
if (displayService == null) return;
6969

7070
for (final ModuleItem<?> outputItem : module.getInfo().outputs()) {
71+
if (module.isOutputResolved(outputItem.getName())) continue;
7172
final Object value = outputItem.getValue(module);
7273
final String name = defaultName(outputItem);
73-
handleOutput(name, value);
74+
final boolean resolved = handleOutput(name, value);
75+
if (resolved) module.resolveOutput(name);
7476
}
7577
}
7678

@@ -82,17 +84,14 @@ public void process(final Module module) {
8284
* @param defaultName The default name for the display, if not already set.
8385
* @param output The object to display.
8486
*/
85-
private void handleOutput(final String defaultName, final Object output) {
86-
if (output == null) {
87-
// ignore null outputs
88-
return;
89-
}
87+
private boolean handleOutput(final String defaultName, final Object output) {
88+
if (output == null) return false; // ignore null outputs
9089

9190
if (output instanceof Display) {
9291
// output is itself a display; just update it
9392
final Display<?> display = (Display<?>) output;
9493
display.update();
95-
return;
94+
return true;
9695
}
9796

9897
final boolean addToExisting = addToExisting(output);
@@ -133,7 +132,7 @@ private void handleOutput(final String defaultName, final Object output) {
133132
for (final Display<?> display : displays) {
134133
display.update();
135134
}
136-
return;
135+
return true;
137136
}
138137

139138
if (output instanceof Map) {
@@ -144,7 +143,7 @@ private void handleOutput(final String defaultName, final Object output) {
144143
final Object itemValue = map.get(key);
145144
handleOutput(itemName, itemValue);
146145
}
147-
return;
146+
return true;
148147
}
149148

150149
if (output instanceof Collection) {
@@ -153,7 +152,7 @@ private void handleOutput(final String defaultName, final Object output) {
153152
for (final Object item : collection) {
154153
handleOutput(defaultName, item);
155154
}
156-
return;
155+
return true;
157156
}
158157

159158
// no available displays for this type of output
@@ -162,6 +161,7 @@ private void handleOutput(final String defaultName, final Object output) {
162161
log.warn("Ignoring unsupported output: " + defaultName + " [" +
163162
valueClass + "]");
164163
}
164+
return false;
165165
}
166166

167167
private boolean addToExisting(final Object output) {

src/main/java/org/scijava/module/AbstractModule.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,16 @@ public abstract class AbstractModule implements Module {
4848
private final HashMap<String, Object> inputs;
4949
private final HashMap<String, Object> outputs;
5050

51-
/** Table indicating resolved inputs. */
5251
private final HashSet<String> resolvedInputs;
52+
private final HashSet<String> resolvedOutputs;
5353

5454
private MethodRef initializerRef;
5555

5656
public AbstractModule() {
5757
inputs = new HashMap<>();
5858
outputs = new HashMap<>();
5959
resolvedInputs = new HashSet<>();
60+
resolvedOutputs = new HashSet<>();
6061
}
6162

6263
// -- Module methods --
@@ -137,14 +138,33 @@ public void setOutputs(final Map<String, Object> outputs) {
137138
}
138139

139140
@Override
140-
public boolean isResolved(final String name) {
141+
public boolean isInputResolved(final String name) {
141142
return resolvedInputs.contains(name);
142143
}
143144

144145
@Override
145-
public void setResolved(final String name, final boolean resolved) {
146-
if (resolved) resolvedInputs.add(name);
147-
else resolvedInputs.remove(name);
146+
public boolean isOutputResolved(final String name) {
147+
return resolvedOutputs.contains(name);
148+
}
149+
150+
@Override
151+
public void resolveInput(final String name) {
152+
resolvedInputs.add(name);
153+
}
154+
155+
@Override
156+
public void resolveOutput(final String name) {
157+
resolvedOutputs.add(name);
158+
}
159+
160+
@Override
161+
public void unresolveInput(final String name) {
162+
resolvedInputs.remove(name);
163+
}
164+
165+
@Override
166+
public void unresolveOutput(final String name) {
167+
resolvedOutputs.remove(name);
148168
}
149169

150170
// -- Helper methods --

src/main/java/org/scijava/module/DefaultModuleService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ private void assignInputs(final Module module,
459459
}
460460
}
461461
module.setInput(name, converted);
462-
module.setResolved(name, true);
462+
module.resolveInput(name);
463463
}
464464
}
465465

@@ -480,7 +480,7 @@ private ModuleItem<?> getSingleItem(final Module module,
480480

481481
for (final ModuleItem<?> item : items) {
482482
final String name = item.getName();
483-
final boolean resolved = module.isResolved(name);
483+
final boolean resolved = module.isInputResolved(name);
484484
if (resolved) continue; // skip resolved inputs
485485
if (!item.isAutoFill()) continue; // skip unfillable inputs
486486
final Class<?> itemType = item.getType();

src/main/java/org/scijava/module/Module.java

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333

3434
import java.util.Map;
3535

36+
import org.scijava.display.DisplayPostprocessor;
37+
import org.scijava.module.process.ModulePostprocessor;
38+
import org.scijava.module.process.ModulePreprocessor;
39+
import org.scijava.widget.InputHarvester;
40+
3641
/**
3742
* A module is an encapsulated piece of functionality with inputs and outputs.
3843
* <p>
@@ -126,15 +131,71 @@ public interface Module extends Runnable {
126131
void setOutputs(Map<String, Object> outputs);
127132

128133
/**
129-
* Gets the resolution status of the input with the given name. A "resolved"
130-
* input is known to have a final, valid value for use with the module.
134+
* Gets the resolution status of the input with the given name.
135+
*
136+
* @see #resolveInput(String)
137+
*/
138+
boolean isInputResolved(String name);
139+
140+
/**
141+
* Gets the resolution status of the output with the given name.
142+
*
143+
* @see #resolveOutput(String)
144+
*/
145+
boolean isOutputResolved(String name);
146+
147+
/**
148+
* Marks the input with the given name as resolved. A "resolved" input is
149+
* known to have a final, valid value for use with the module.
150+
* <p>
151+
* {@link ModulePreprocessor}s in the module execution chain that populate
152+
* input values (e.g. {@link InputHarvester} plugins) will typically skip over
153+
* inputs which have already been resolved.
154+
* </p>
155+
*/
156+
void resolveInput(String name);
157+
158+
/**
159+
* Marks the output with the given name as resolved. A "resolved" output has
160+
* been handled by the framework somehow, typically displayed to the user.
161+
* <p>
162+
* {@link ModulePostprocessor}s in the module execution chain that handle
163+
* output values (e.g. the {@link DisplayPostprocessor}) will typically skip
164+
* over outputs which have already been resolved.
165+
* </p>
166+
*/
167+
void resolveOutput(String name);
168+
169+
/**
170+
* Marks the input with the given name as unresolved.
171+
*
172+
* @see #resolveInput(String)
131173
*/
132-
boolean isResolved(String name);
174+
void unresolveInput(String name);
175+
176+
/**
177+
* Marks the output with the given name as unresolved.
178+
*
179+
* @see #resolveOutput(String)
180+
*/
181+
void unresolveOutput(String name);
182+
183+
// -- Deprecated --
184+
185+
/** @deprecated Use {@link #isInputResolved(String)} instead. */
186+
@Deprecated
187+
default boolean isResolved(final String name) {
188+
return isInputResolved(name);
189+
}
133190

134191
/**
135-
* Sets the resolution status of the input with the given name. A "resolved"
136-
* input is known to have a final, valid value for use with the module.
192+
* @deprecated Use {@link #resolveInput(String)} and
193+
* {@link #unresolveInput(String)} instead.
137194
*/
138-
void setResolved(String name, boolean resolved);
195+
@Deprecated
196+
default void setResolved(final String name, final boolean resolved) {
197+
if (resolved) resolveInput(name);
198+
else unresolveInput(name);
199+
}
139200

140201
}

src/main/java/org/scijava/module/process/DefaultValuePreprocessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public void process(final Module module) {
7272
private <T> void assignDefaultValue(final Module module,
7373
final ModuleItem<T> item)
7474
{
75-
if (module.isResolved(item.getName())) return;
75+
if (module.isInputResolved(item.getName())) return;
7676
final T nullValue = ConversionUtils.getNullValue(item.getType());
7777
if (Objects.equals(item.getValue(module), nullValue)) return;
7878
final T defaultValue = moduleService.getDefaultValue(item);

src/main/java/org/scijava/module/process/GatewayPreprocessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ private <G extends Gateway> void setGatewayValue(final Context context,
110110
return;
111111
}
112112
input.setValue(module, gateway);
113-
module.setResolved(input.getName(), true);
113+
module.resolveInput(input.getName());
114114
}
115115

116116
}

src/main/java/org/scijava/module/process/LoadInputsPreprocessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public void process(final Module module) {
7676
/** Loads the value of the given module item from persistent storage. */
7777
private <T> void loadValue(final Module module, final ModuleItem<T> item) {
7878
// skip input that has already been resolved
79-
if (module.isResolved(item.getName())) return;
79+
if (module.isInputResolved(item.getName())) return;
8080

8181
final T prefValue = moduleService.load(item);
8282
final Class<T> type = item.getType();

0 commit comments

Comments
 (0)