Skip to content

Commit 52ca72f

Browse files
gselzerctrueden
authored andcommitted
Create SciJava Ops ServiceLoader module
Adds a Discoverer responsible for looking up implementations via ServiceLoader
1 parent e447fa2 commit 52ca72f

17 files changed

Lines changed: 563 additions & 67 deletions

File tree

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
<module>scijava/scijava-ops-api</module>
5353
<module>scijava/scijava-ops-discovery</module>
5454
<module>scijava/scijava-ops-engine</module>
55+
<module>scijava/scijava-ops-serviceloader</module>
5556
<module>scijava/scijava-ops-spi</module>
5657
<module>scijava/scijava-struct</module>
5758
<module>scijava/scijava-taglets</module>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55

66
public interface Discoverer {
77

8-
<T> List<? extends Class<T>> implementingClasses(Class<T> c);
8+
<T> List<Class<T>> implementingClasses(Class<T> c);
99

1010
}

scijava/scijava-ops-discovery/src/main/java/org/scijava/ops/discovery/StaticDiscoverer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public void register(Class<?> c, String name) {
2020

2121
@SuppressWarnings("unchecked")
2222
@Override
23-
public <T> List<? extends Class<T>> implementingClasses(Class<T> c) {
23+
public <T> List<Class<T>> implementingClasses(Class<T> c) {
2424
return names.keySet().stream() //
2525
.filter(cls -> cls.isAssignableFrom(c)) //
2626
.map(cls -> (Class<T>) cls) //
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
package org.scijava.ops.engine.impl;
3+
4+
import java.util.Arrays;
5+
import java.util.List;
6+
import java.util.stream.Collectors;
7+
8+
import org.scijava.ops.api.OpInfo;
9+
import org.scijava.ops.api.OpInfoGenerator;
10+
import org.scijava.ops.api.OpUtils;
11+
import org.scijava.ops.discovery.Discoverer;
12+
import org.scijava.ops.engine.matcher.impl.OpClassInfo;
13+
import org.scijava.ops.spi.Op;
14+
import org.scijava.plugin.Plugin;
15+
16+
public class ClassOpInfoGenerator implements OpInfoGenerator {
17+
18+
private final List<Discoverer> discoverers;
19+
20+
public ClassOpInfoGenerator(Discoverer... d) {
21+
this.discoverers = Arrays.asList(d);
22+
}
23+
24+
@Override
25+
public List<OpInfo> generateInfos() {
26+
List<OpInfo> infos = discoverers.stream() //
27+
.flatMap(d -> d.implementingClasses(Op.class).stream()) //
28+
.filter(cls -> cls.getAnnotation(Plugin.class) != null) //
29+
.map(cls -> {
30+
Plugin p = cls.getAnnotation(Plugin.class);
31+
String[] parsedOpNames = OpUtils.parseOpNames(p.name());
32+
return new OpClassInfo(cls, parsedOpNames);
33+
}) //
34+
.collect(Collectors.toList());
35+
return infos;
36+
}
37+
38+
}

scijava/scijava-ops-engine/src/main/java/org/scijava/ops/engine/impl/DefaultOpService.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import org.scijava.ops.api.OpEnvironment;
4141
import org.scijava.ops.api.OpInfoGenerator;
4242
import org.scijava.ops.discovery.Discoverer;
43-
import org.scijava.ops.discovery.Implementation;
4443
import org.scijava.ops.engine.OpHistoryService;
4544
import org.scijava.ops.engine.OpService;
4645
import org.scijava.plugin.Plugin;
@@ -88,15 +87,14 @@ public OpEnvironment env() {
8887

8988
private synchronized void initEnv() {
9089
if (env != null) return;
91-
PluginService plugins = context().getService(PluginService.class);
9290
LogService log = context().getService(LogService.class);
9391
TypeService types = context().getService(TypeService.class);
9492
OpHistoryService history = context().getService(OpHistoryService.class);
93+
Discoverer d = new PluginBasedDiscoverer(context());
9594
List<OpInfoGenerator> infoGenerators = Arrays.asList(
96-
new PluginBasedClassOpInfoGenerator(plugins),
97-
new PluginBasedOpCollectionInfoGenerator(plugins));
98-
env = new DefaultOpEnvironment(types, log, history,
99-
infoGenerators, new PluginBasedDiscoverer(context()));
95+
new ClassOpInfoGenerator(d),
96+
new OpCollectionInfoGenerator(d));
97+
env = new DefaultOpEnvironment(types, log, history, infoGenerators, d);
10098
}
10199
}
102100

@@ -110,7 +108,7 @@ public PluginBasedDiscoverer(Context ctx) {
110108

111109
@Override
112110
@SuppressWarnings("unchecked")
113-
public <T> List<? extends Class<T>> implementingClasses(Class<T> c) {
111+
public <T> List<Class<T>> implementingClasses(Class<T> c) {
114112
if (!SciJavaPlugin.class.isAssignableFrom(c)) {
115113
throw new UnsupportedOperationException(
116114
"Current discovery mechanism tied to SciJava Context; only able to search for SciJavaPlugins");

scijava/scijava-ops-engine/src/main/java/org/scijava/ops/engine/impl/PluginBasedOpCollectionInfoGenerator.java renamed to scijava/scijava-ops-engine/src/main/java/org/scijava/ops/engine/impl/OpCollectionInfoGenerator.java

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,41 @@
44
import java.lang.reflect.Method;
55
import java.lang.reflect.Modifier;
66
import java.util.ArrayList;
7+
import java.util.Arrays;
78
import java.util.List;
9+
import java.util.stream.Collectors;
810

911
import org.scijava.InstantiableException;
1012
import org.scijava.ops.api.OpInfo;
1113
import org.scijava.ops.api.OpInfoGenerator;
1214
import org.scijava.ops.api.OpUtils;
15+
import org.scijava.ops.discovery.Discoverer;
1316
import org.scijava.ops.engine.matcher.impl.OpFieldInfo;
1417
import org.scijava.ops.engine.matcher.impl.OpMethodInfo;
1518
import org.scijava.ops.spi.OpCollection;
1619
import org.scijava.ops.spi.OpField;
1720
import org.scijava.ops.spi.OpMethod;
18-
import org.scijava.plugin.PluginInfo;
19-
import org.scijava.plugin.PluginService;
21+
import org.scijava.plugin.Plugin;
2022
import org.scijava.util.ClassUtils;
2123

2224

23-
public class PluginBasedOpCollectionInfoGenerator implements OpInfoGenerator {
25+
public class OpCollectionInfoGenerator implements OpInfoGenerator {
2426

25-
private final PluginService service;
27+
private final List<Discoverer> discoverers;
2628

27-
public PluginBasedOpCollectionInfoGenerator(PluginService service) {
28-
this.service = service;
29+
public OpCollectionInfoGenerator(Discoverer... d) {
30+
this.discoverers = Arrays.asList(d);
2931
}
3032

3133
@Override
3234
public List<OpInfo> generateInfos() {
33-
List<OpInfo> infos = new ArrayList<>();
34-
for (PluginInfo<OpCollection> info : service.getPluginsOfType(OpCollection.class) ) {
35+
List<OpInfo> infos = discoverers.stream() //
36+
.flatMap(d -> d.implementingClasses(OpCollection.class).stream()) //
37+
.filter(cls -> cls.getAnnotation(Plugin.class) != null) //
38+
.map(cls -> {
3539
try {
36-
Class<?> c = info.loadClass();
37-
final List<Field> fields = ClassUtils.getAnnotatedFields(c, OpField.class);
40+
List<OpInfo> collectionInfos = new ArrayList<>();
41+
final List<Field> fields = ClassUtils.getAnnotatedFields(cls, OpField.class);
3842
Object instance = null;
3943
for (Field field : fields) {
4044
final boolean isStatic = Modifier.isStatic(field.getModifiers());
@@ -43,20 +47,25 @@ public List<OpInfo> generateInfos() {
4347
}
4448
String unparsedOpNames = field.getAnnotation(OpField.class).names();
4549
String[] parsedOpNames = OpUtils.parseOpNames(unparsedOpNames);
46-
infos.add(new OpFieldInfo(isStatic ? null : instance, field,
50+
collectionInfos.add(new OpFieldInfo(isStatic ? null : instance, field,
4751
parsedOpNames));
4852
}
49-
final List<Method> methods = ClassUtils.getAnnotatedMethods(c, OpMethod.class);
53+
final List<Method> methods = ClassUtils.getAnnotatedMethods(cls, OpMethod.class);
5054
for (final Method method: methods) {
5155
String unparsedOpNames = method.getAnnotation(OpMethod.class).names();
5256
String[] parsedOpNames = OpUtils.parseOpNames(unparsedOpNames);
53-
infos.add(new OpMethodInfo(method, parsedOpNames));
57+
collectionInfos.add(new OpMethodInfo(method, parsedOpNames));
5458
}
55-
} catch (InstantiationException | IllegalAccessException | InstantiableException exc) {
59+
return collectionInfos;
60+
} catch (InstantiationException | IllegalAccessException exc) {
5661
// TODO: Consider how best to handle this.
57-
exc.printStackTrace();
62+
return null;
5863
}
59-
}
64+
65+
}) //
66+
.filter(list -> list!= null) //
67+
.flatMap(list -> list.stream()) //
68+
.collect(Collectors.toList());
6069
return infos;
6170
}
6271

scijava/scijava-ops-engine/src/main/java/org/scijava/ops/engine/impl/PluginBasedClassOpInfoGenerator.java

Lines changed: 0 additions & 42 deletions
This file was deleted.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/.apt_generated/
2+
/.apt_generated_tests/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Copyright (c) 2016 - 2019, SciJava Ops developers.
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without modification,
5+
are permitted provided that the following conditions are met:
6+
7+
1. Redistributions of source code must retain the above copyright notice, this
8+
list of conditions and the following disclaimer.
9+
10+
2. Redistributions in binary form must reproduce the above copyright notice,
11+
this list of conditions and the following disclaimer in the documentation
12+
and/or other materials provided with the distribution.
13+
14+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24+
POSSIBILITY OF SUCH DAMAGE.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SciJava Discovery: A library for the abstraction of service discovery mechanisms
2+
3+
This module provides the `Discoverer` interface, an abstraction for service discovery.
4+
5+
WIP

0 commit comments

Comments
 (0)