3131
3232package org .scijava .module ;
3333
34+ import java .util .List ;
35+
36+ import org .scijava .Identifiable ;
37+ import org .scijava .Locatable ;
3438import org .scijava .UIDetails ;
3539import org .scijava .Validated ;
40+ import org .scijava .ValidityProblem ;
41+ import org .scijava .Versioned ;
3642import org .scijava .event .EventService ;
3743import org .scijava .module .event .ModulesUpdatedEvent ;
44+ import org .scijava .util .ClassUtils ;
45+ import org .scijava .util .VersionUtils ;
3846
3947/**
4048 * A ModuleInfo object encapsulates metadata about a particular {@link Module}
4957 * @author Aivar Grislis
5058 * @author Curtis Rueden
5159 */
52- public interface ModuleInfo extends UIDetails , Validated {
60+ public interface ModuleInfo extends UIDetails , Validated , Identifiable ,
61+ Locatable , Versioned
62+ {
5363
5464 /** Gets the input item with the given name. */
5565 ModuleItem <?> getInput (String name );
@@ -116,15 +126,19 @@ public interface ModuleInfo extends UIDetails, Validated {
116126 * means its inputs are supposed to be presented in a non-modal dialog box,
117127 * with {@link Module#run()} being called whenever any of the values change.
118128 */
119- boolean isInteractive ();
129+ default boolean isInteractive () {
130+ return false ;
131+ }
120132
121133 /**
122134 * Gets whether the module supports previews. A preview is a quick
123135 * approximation of the results that would be obtained by actually executing
124136 * the module with {@link Module#run()}. If this method returns false, then
125137 * calling {@link Module#preview()} will have no effect.
126138 */
127- boolean canPreview ();
139+ default boolean canPreview () {
140+ return false ;
141+ }
128142
129143 /**
130144 * Gets whether the module condones cancellation. Strictly speaking, any
@@ -133,29 +147,97 @@ public interface ModuleInfo extends UIDetails, Validated {
133147 * If this method returns false, then calling {@link Module#cancel()} will
134148 * have no effect.
135149 */
136- boolean canCancel ();
150+ default boolean canCancel () {
151+ return true ;
152+ }
137153
138154 /**
139155 * Gets whether the module condones headless execution. Strictly speaking,
140156 * there is no guarantee that any module will work headless just because it
141157 * declares itself so, but this flag hints that headless execution is likely
142158 * to succeed (if flag is true), or fail (if flag is false).
143159 */
144- boolean canRunHeadless ();
160+ default boolean canRunHeadless () {
161+ return false ;
162+ }
145163
146164 /** Gets the function that is called to initialize the module's values. */
147- String getInitializer ();
165+ default String getInitializer () {
166+ return null ;
167+ }
148168
149169 /**
150170 * Notifies interested parties that the module info has been modified. This
151171 * mechanism is useful for updating any corresponding user interface such as
152172 * menu items that are linked to the module.
153- * <p>
154- * For classes implementing this interface directly, this method should
155- * publish a {@link ModulesUpdatedEvent} to the event bus (see
156- * {@link AbstractModuleInfo#update(EventService)} for an example).
157- * </p>
158173 */
159- void update (EventService eventService );
160-
174+ default void update (final EventService eventService ) {
175+ eventService .publish (new ModulesUpdatedEvent (this ));
176+ }
177+
178+ // -- UIDetails methods --
179+
180+ @ Override
181+ default String getTitle () {
182+ final String title = UIDetails .super .getTitle ();
183+ if (!title .equals (getClass ().getSimpleName ())) return title ;
184+
185+ // use delegate class name rather than actual class name
186+ final String className = getDelegateClassName ();
187+ final int dot = className .lastIndexOf ("." );
188+ return dot < 0 ? className : className .substring (dot + 1 );
189+ }
190+
191+ // -- Validated methods --
192+
193+ @ Override
194+ default boolean isValid () {
195+ return true ;
196+ }
197+
198+ @ Override
199+ default List <ValidityProblem > getProblems () {
200+ return null ;
201+ }
202+
203+ // -- Identifiable methods --
204+
205+ @ Override
206+ default String getIdentifier () {
207+ // NB: By default, we assume that the delegate class name uniquely
208+ // distinguishes the module from others. If the same delegate class is used
209+ // for more than one module, though, it may need to override this method to
210+ // provide more differentiating details.
211+ return "module:" + getDelegateClassName ();
212+ }
213+
214+ // -- Locatable methods --
215+
216+ @ Override
217+ default String getLocation () {
218+ // NB: By default, we use the location of the delegate class.
219+ // If the same delegate class is used for more than one module, though,
220+ // it may need to override this method to indicate a different location.
221+ try {
222+ return ClassUtils .getLocation (loadDelegateClass ()).toExternalForm ();
223+ }
224+ catch (final ClassNotFoundException exc ) {
225+ return null ;
226+ }
227+ }
228+
229+ // -- Versioned methods --
230+
231+ @ Override
232+ default String getVersion () {
233+ // NB: By default, we use the version of the delegate class's JAR archive.
234+ // If the same delegate class is used for more than one module, though,
235+ // it may need to override this method to indicate a different version.
236+ try {
237+ return VersionUtils .getVersion (loadDelegateClass ());
238+ }
239+ catch (final ClassNotFoundException exc ) {
240+ return null ;
241+ }
242+ }
161243}
0 commit comments