3030package org .scijava .discovery ;
3131
3232import java .lang .reflect .Type ;
33- import java .util .ArrayList ;
34- import java .util .Arrays ;
35- import java .util .Collection ;
36- import java .util .Collections ;
37- import java .util .Comparator ;
38- import java .util .List ;
39- import java .util .Optional ;
40- import java .util .ServiceConfigurationError ;
41- import java .util .ServiceLoader ;
33+ import java .util .*;
4234import java .util .function .Function ;
4335import java .util .stream .Collectors ;
44- import java .util .stream .Stream ;
4536import java .util .stream .StreamSupport ;
4637
4738/**
@@ -62,72 +53,65 @@ public interface Discoverer {
6253 <U > List <U > discover (Class <U > c );
6354
6455 /**
65- * Creates a {@link Discoverer} operating via {@link ServiceLoader }.
56+ * Creates a {@link Discoverer} operating via {@link Function }.
6657 * <p>
67- * NB: The {@link Function} input is extremely important for JPMS
58+ * NB: The {@link Function} input is extremely important for e.g. JPMS
6859 * compatibility. This puts the code loading the services into the user's
69- * module, allowing access to all of the services exposed to (and
70- * {@code use}d by) the calling module. Otherwise, all service interfaces
71- * would have to be {@code use}d by <b>this</b> module, which is not
72- * extensible.
60+ * module, allowing access to all of the services exposed to (and {@code use}d
61+ * by) the calling module. Otherwise, all service interfaces would have to be
62+ * {@code use}d by <b>this</b> module, which is not extensible.
7363 * </p>
7464 *
75- * @param func the {@link Function} generating a {@link ServiceLoader}
65+ * @param func the {@link Function} generating a {@link Iterable} of
66+ * implementations provided a {@link Class}
7667 * @param <T> the {@link Class} we attempt to discover, and consequently the
77- * supertype of all implementations returned by {@link ServiceLoader }
78- * @return A {@link Discoverer} backed by {@link ServiceLoader }
68+ * supertype of all implementations contained in the {@link Iterable }
69+ * @return A {@link Discoverer} backed by {@code func }
7970 */
80- static <T > Discoverer using (
81- Function <Class <T >, ? extends ServiceLoader <T >> func )
82- {
71+ static <T > Discoverer using (Function <Class <T >, ? extends Iterable <T >> func ) {
8372 return new Discoverer () {
8473
8574 @ Override
8675 public <U > List <U > discover (Class <U > c ) {
8776 // If we can use c, look up the implementations
8877 try {
89- Iterable <U > itr = (ServiceLoader <U >) func .apply ((Class <T >) c );
78+ Iterable <U > itr = (Iterable <U >) func .apply ((Class <T >) c );
9079 return StreamSupport .stream (itr .spliterator (), false ).collect (
9180 Collectors .toList ());
9281 }
93- catch (ClassCastException e ) {
94- return Collections .emptyList ();
95- }
96- catch (ServiceConfigurationError e ) {
82+ catch (ClassCastException | ServiceConfigurationError e ) {
9783 return Collections .emptyList ();
9884 }
9985 }
10086 };
10187 }
10288
103- static Iterable <Discoverer > allProvided () {
104- return ServiceLoader .load (Discoverer .class );
105- }
106-
10789 /**
108- * Gets all {@link Discoverer}s made available through {@link ServiceLoader},
109- * as well as a {@link Discoverer} that is itself backed by
110- * {@link ServiceLoader}.
90+ * Gets all {@link Discoverer}s made available through {@link Iterable}, as
91+ * well as a {@link Discoverer} that is itself backed by the {@link Iterable}.
11192 * <p>
11293 * It is <b>highly</b> recommended to call this method using {@code
11394 * List<Discoverer> discoverers = Discoverers.all(ServiceLoader::load);
11495 * }
11596 *
116- * @param func A callbacks used to get the module scope of the caller. Through
117- * {@code func}, the {@link ServiceLoader}-based {@link Discoverer}
118- * is capable of discovering all interfaces {@code use}d by the
119- * caller module. If we instead called
120- * {@link ServiceLoader#load(Class)} directly, we'd only be able to
121- * discover implementations whose interface was {@code use}d by
122- * {@code module org.scijava.discovery}.
97+ * @param func the {@link Function} generating a {@link Iterable} of
98+ * implementations provided a {@link Class}. Notably, this callback
99+ * has the module scope of the caller, which is useful for
100+ * circumnavigating module permissions when using e.g. JPMS. If we
101+ * instead used {@link ServiceLoader#load(Class)} directly, we'd only
102+ * be able to discover implementations whose interface was
103+ * {@code use}d by {@code module org.scijava.discovery}.
123104 * <p>
124105 * It is in the user's best interest to make this {@link Function} as
125106 * general as possible.
126- * @param <T>
127- * @return
107+ * @param <T> the {@link Class} we attempt to discover, and consequently the
108+ * supertype of all implementations contained in the {@link Iterable}
109+ * @return A {@link List} of {@link Discoverer}s, including a
110+ * {@code Discoverer} backed by {@code func}, and all
111+ * {@link Discoverer}s found by {@code func}
128112 */
129113 static <T > List <Discoverer > all (
130- Function <Class <T >, ? extends ServiceLoader <T >> func )
114+ Function <Class <T >, ? extends Iterable <T >> func )
131115 {
132116 // First, create the general-purpose Discoverer using the
133117 // using(Function<...>)
@@ -151,7 +135,7 @@ static <T> List<Discoverer> all(
151135 * @param discoverers the {@link Discoverer}s to be wrapped
152136 * @return the mega-{@link Discoverer}
153137 */
154- public static Discoverer union (Iterable <Discoverer > discoverers ) {
138+ static Discoverer union (Iterable <Discoverer > discoverers ) {
155139
156140 return new Discoverer () {
157141
0 commit comments