Skip to content

Commit ab4d12e

Browse files
gselzerctrueden
authored andcommitted
Discoverer: Broaden param types & other changes
1 parent 69f7e88 commit ab4d12e

File tree

1 file changed

+29
-45
lines changed

1 file changed

+29
-45
lines changed

scijava-discovery/src/main/java/org/scijava/discovery/Discoverer.java

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,9 @@
3030
package org.scijava.discovery;
3131

3232
import 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.*;
4234
import java.util.function.Function;
4335
import java.util.stream.Collectors;
44-
import java.util.stream.Stream;
4536
import 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

Comments
 (0)