Skip to content

Commit 66ed844

Browse files
committed
Add a rudimentary input validation mechanism
Now, if you want to validate that the value of an input is acceptable, you can specify a validater method which will be called when that input is marked as resolved. Admittedly, this is a bit late in the module execution process, and dynamic validation would still be nice in the future (e.g., to provide feedback as values are updated in input harvester UIs). But the good thing about this scheme is that regardless of which preprocessor locks in the parameter value, validation will be called immediately afterward, before the next preprocessor runs. Thanks to Richard Domander for the idea and discussion.
1 parent d52961b commit 66ed844

File tree

8 files changed

+69
-0
lines changed

8 files changed

+69
-0
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ public String getInitializer() {
123123
return getParameter().initializer();
124124
}
125125

126+
@Override
127+
public String getValidater() {
128+
return getParameter().validater();
129+
}
130+
126131
@Override
127132
public String getCallback() {
128133
return getParameter().callback();

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,16 @@ public boolean isOutputResolved(final String name) {
149149

150150
@Override
151151
public void resolveInput(final String name) {
152+
final ModuleItem<?> item = getInputItem(name);
153+
if (item != null) {
154+
try {
155+
item.validate(this);
156+
}
157+
catch (final MethodCallException exc) {
158+
// NB: Hacky, but avoids changing the API signature.
159+
throw new RuntimeException(exc);
160+
}
161+
}
152162
resolvedInputs.add(name);
153163
}
154164

@@ -181,4 +191,10 @@ private Map<String, Object> createMap(final Iterable<ModuleItem<?>> items,
181191
return map;
182192
}
183193

194+
private ModuleItem<?> getInputItem(final String name) {
195+
for (final ModuleItem<?> item : getInfo().inputs()) {
196+
if (item.getName().equals(name)) return item;
197+
}
198+
return null;
199+
}
184200
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public abstract class AbstractModuleItem<T> extends AbstractBasicDetails
5656
private final ModuleInfo info;
5757

5858
private MethodRef initializerRef;
59+
private MethodRef validaterRef;
5960
private MethodRef callbackRef;
6061

6162
public AbstractModuleItem(final ModuleInfo info) {
@@ -200,6 +201,20 @@ public void initialize(final Module module) throws MethodCallException {
200201
initializerRef.execute(module.getDelegateObject());
201202
}
202203

204+
@Override
205+
public String getValidater() {
206+
return null;
207+
}
208+
209+
@Override
210+
public void validate(final Module module) throws MethodCallException {
211+
final Object delegateObject = module.getDelegateObject();
212+
if (validaterRef == null) {
213+
validaterRef = new MethodRef(delegateObject.getClass(), getValidater());
214+
}
215+
validaterRef.execute(module.getDelegateObject());
216+
}
217+
203218
@Override
204219
public String getCallback() {
205220
return null;

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public class DefaultMutableModuleItem<T> extends AbstractModuleItem<T>
5757
private boolean persisted;
5858
private String persistKey;
5959
private String initializer;
60+
private String validater;
6061
private String callback;
6162
private String widgetStyle;
6263
private T defaultValue;
@@ -162,6 +163,11 @@ public void setInitializer(final String initializer) {
162163
this.initializer = initializer;
163164
}
164165

166+
@Override
167+
public void setValidater(final String validater) {
168+
this.validater = validater;
169+
}
170+
165171
@Override
166172
public void setCallback(final String callback) {
167173
this.callback = callback;
@@ -255,6 +261,11 @@ public String getInitializer() {
255261
return initializer;
256262
}
257263

264+
@Override
265+
public String getValidater() {
266+
return validater;
267+
}
268+
258269
@Override
259270
public String getCallback() {
260271
return callback;

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ public interface ModuleItem<T> extends BasicDetails {
123123
*/
124124
void initialize(Module module) throws MethodCallException;
125125

126+
/** Gets the function that is called to validate the item's value. */
127+
String getValidater();
128+
129+
/**
130+
* Invokes this item's validation function, if any, on the given module.
131+
*
132+
* @see #getValidater()
133+
*/
134+
void validate(Module module) throws MethodCallException;
135+
126136
/**
127137
* Gets the function that is called whenever this item changes.
128138
* <p>

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public interface MutableModuleItem<T> extends ModuleItem<T> {
5656

5757
void setInitializer(String initializer);
5858

59+
void setValidater(String validater);
60+
5961
void setCallback(String callback);
6062

6163
void setWidgetStyle(String widgetStyle);

src/main/java/org/scijava/plugin/Parameter.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
import org.scijava.ItemIO;
4040
import org.scijava.ItemVisibility;
41+
import org.scijava.module.Module;
4142

4243
/**
4344
* An annotation for indicating a field is an input or output parameter. This
@@ -119,6 +120,14 @@
119120
/** Defines a function that is called to initialize the parameter. */
120121
String initializer() default "";
121122

123+
/**
124+
* Defines a function that is called to validate the parameter value after it
125+
* is marked as resolved.
126+
*
127+
* @see Module#resolveInput(String)
128+
*/
129+
String validater() default "";
130+
122131
/**
123132
* Defines a function that is called whenever this parameter changes.
124133
* <p>

src/main/java/org/scijava/script/ScriptInfo.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ private <T> void assignAttribute(final DefaultMutableModuleItem<T> item,
488488
else if (is(k, "columns")) item.setColumnCount(as(v, int.class));
489489
else if (is(k, "description")) item.setDescription(as(v, String.class));
490490
else if (is(k, "initializer")) item.setInitializer(as(v, String.class));
491+
else if (is(k, "validater")) item.setValidater(as(v, String.class));
491492
else if (is(k, "type")) item.setIOType(as(v, ItemIO.class));
492493
else if (is(k, "label")) item.setLabel(as(v, String.class));
493494
else if (is(k, "max")) item.setMaximumValue(as(v, item.getType()));

0 commit comments

Comments
 (0)