Skip to content

Commit 9eae5fa

Browse files
wiedenmctrueden
andcommitted
Remove service natures
From OpTypeMatchingService and OpTransformerService, and rename them accordingly. This commit also separates indexing transformers from matching them by moving the indexing logic to OpService. Co-authored-by: Curtis Rueden <ctrueden@wisc.edu>
1 parent 4fde521 commit 9eae5fa

File tree

10 files changed

+118
-107
lines changed

10 files changed

+118
-107
lines changed

src/main/java/org/scijava/ops/OpService.java

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,21 @@
7676
import org.scijava.ops.core.inplace.InplaceOps.Inplace6FirstOp;
7777
import org.scijava.ops.core.inplace.InplaceOps.Inplace7SecondOp;
7878
import org.scijava.ops.core.inplace.InplaceOps.InplaceOp;
79+
import org.scijava.ops.matcher.DefaultOpMatcher;
7980
import org.scijava.ops.matcher.OpCandidate;
8081
import org.scijava.ops.matcher.OpClassInfo;
8182
import org.scijava.ops.matcher.OpFieldInfo;
8283
import org.scijava.ops.matcher.OpInfo;
8384
import org.scijava.ops.matcher.OpMatchingException;
8485
import org.scijava.ops.matcher.OpRef;
85-
import org.scijava.ops.matcher.OpTypeMatchingService;
86+
import org.scijava.ops.matcher.OpMatcher;
87+
import org.scijava.ops.transform.DefaultOpTransformationMatcher;
8688
import org.scijava.ops.transform.OpRunner;
8789
import org.scijava.ops.transform.OpTransformationCandidate;
8890
import org.scijava.ops.transform.OpTransformationException;
89-
import org.scijava.ops.transform.OpTransformerService;
9091
import org.scijava.ops.types.Any;
92+
import org.scijava.ops.transform.OpTransformationMatcher;
93+
import org.scijava.ops.transform.OpTransformer;
9194
import org.scijava.ops.types.Nil;
9295
import org.scijava.ops.types.TypeService;
9396
import org.scijava.param.FunctionalMethodType;
@@ -115,14 +118,12 @@ public class OpService extends AbstractService implements SciJavaService, OpEnvi
115118
@Parameter
116119
private PluginService pluginService;
117120

118-
@Parameter
119-
private OpTypeMatchingService matcher;
121+
private OpMatcher opMatcher;
120122

121123
@Parameter
122124
private LogService log;
123125

124-
@Parameter
125-
private OpTransformerService transformer;
126+
private OpTransformationMatcher transformationMatcher;
126127

127128
@Parameter
128129
private TypeService typeService;
@@ -138,6 +139,8 @@ public class OpService extends AbstractService implements SciJavaService, OpEnvi
138139
*/
139140
private Map<String, List<OpInfo>> opCache;
140141

142+
private List<OpTransformer> transformerIndex;
143+
141144
private static Map<Class<?>, Class<?>> wrappers = wrappers();
142145

143146
private static Map<Class<?>, Class<?>> wrappers() {
@@ -186,8 +189,7 @@ public void initOpCache() {
186189
try {
187190
final Class<?> opClass = pluginInfo.loadClass();
188191
OpInfo opInfo = new OpClassInfo(opClass);
189-
addToCache(opInfo, pluginInfo.getName());
190-
192+
addToOpIndex(opInfo, pluginInfo.getName());
191193
} catch (InstantiableException exc) {
192194
log.error("Can't load class from plugin info: " + pluginInfo.toString(), exc);
193195
}
@@ -204,15 +206,15 @@ public void initOpCache() {
204206
instance = field.getDeclaringClass().newInstance();
205207
}
206208
OpInfo opInfo = new OpFieldInfo(isStatic ? null : instance, field);
207-
addToCache(opInfo, field.getAnnotation(OpField.class).names());
209+
addToOpIndex(opInfo, field.getAnnotation(OpField.class).names());
208210
}
209211
} catch (InstantiableException | InstantiationException | IllegalAccessException exc) {
210212
log.error("Can't load class from plugin info: " + pluginInfo.toString(), exc);
211213
}
212214
}
213215
}
214216

215-
private void addToCache(OpInfo opInfo, String opNames) {
217+
private void addToOpIndex(final OpInfo opInfo, final String opNames) {
216218
String[] parsedOpNames = OpUtils.parseOpNames(opNames);
217219
if (parsedOpNames == null || parsedOpNames.length == 0) {
218220
log.error("Skipping Op " + opInfo.implementationName() + ":\n" + "Op implementation must provide name.");
@@ -230,6 +232,10 @@ private void addToCache(OpInfo opInfo, String opNames) {
230232
}
231233
}
232234

235+
public synchronized void initTransformerIndex() {
236+
transformerIndex = pluginService.createInstancesOfType(OpTransformer.class);
237+
}
238+
233239
@Override
234240
public Iterable<OpInfo> infos() {
235241
if (opCache == null) {
@@ -254,6 +260,27 @@ public Iterable<OpInfo> infos(String name) {
254260
return infos;
255261
}
256262

263+
private OpMatcher getOpMatcher() {
264+
if (opMatcher == null) {
265+
opMatcher = new DefaultOpMatcher(log);
266+
}
267+
return opMatcher;
268+
}
269+
270+
private synchronized List<OpTransformer> getTransformerIndex() {
271+
if (transformerIndex == null) {
272+
initTransformerIndex();
273+
}
274+
return transformerIndex;
275+
}
276+
277+
private OpTransformationMatcher getTransformationMatcher() {
278+
if (transformationMatcher == null) {
279+
transformationMatcher = new DefaultOpTransformationMatcher(getOpMatcher());
280+
}
281+
return transformationMatcher;
282+
}
283+
257284
/**
258285
* Attempts to inject {@link OpDependency} annotated fields of the specified
259286
* object by looking for Ops matching the field type and the name specified in
@@ -310,7 +337,7 @@ public Object findOpInstance(final String opName, final OpRef ref) {
310337
OpTransformationCandidate transformation = null;
311338
try {
312339
// Find single match which matches the specified types
313-
match = matcher.findSingleMatch(this, ref);
340+
match = getOpMatcher().findSingleMatch(this, ref);
314341
final List<Object> dependencies = resolveOpDependencies(match);
315342
op = match.createOp(dependencies);
316343
} catch (OpMatchingException e) {
@@ -319,7 +346,7 @@ public Object findOpInstance(final String opName, final OpRef ref) {
319346

320347
// If we can't find an op matching the original request, we try to find a
321348
// transformation
322-
transformation = transformer.findTransformation(this, ref);
349+
transformation = getTransformationMatcher().findTransformation(this, getTransformerIndex(), ref);
323350
if (transformation == null) {
324351
log.debug("No matching Op transformation found");
325352
throw new IllegalArgumentException(e);

src/main/java/org/scijava/ops/OpUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@
3636
import java.util.Objects;
3737
import java.util.stream.Collectors;
3838

39-
import org.scijava.ops.matcher.DefaultOpTypeMatchingService;
4039
import org.scijava.ops.matcher.MatchingResult;
4140
import org.scijava.ops.matcher.OpCandidate;
4241
import org.scijava.ops.matcher.OpCandidate.StatusCode;
4342
import org.scijava.ops.matcher.OpInfo;
43+
import org.scijava.ops.matcher.OpMatcher;
4444
import org.scijava.ops.matcher.OpRef;
4545
import org.scijava.param.ParameterMember;
4646
import org.scijava.param.ParameterStructs;
@@ -253,7 +253,7 @@ public static List<Member<?>> injectableMembers(Struct struct) {
253253
* several matches that do not have equal output types, the output type may not
254254
* completely match the request as only raw type assignability will be checked
255255
* at the moment.
256-
* @see DefaultOpTypeMatchingService#typesMatch(OpCandidate)
256+
* @see OpMatcher#typesMatch(OpCandidate)
257257
* @param matches
258258
* @return
259259
*/

src/main/java/org/scijava/ops/matcher/DefaultOpTypeMatchingService.java renamed to src/main/java/org/scijava/ops/matcher/DefaultOpMatcher.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,10 @@
4141
import java.util.Objects;
4242
import java.util.function.Predicate;
4343

44-
import org.scijava.Context;
45-
import org.scijava.log.LogService;
44+
import org.scijava.log.Logger;
4645
import org.scijava.ops.OpEnvironment;
4746
import org.scijava.ops.OpUtils;
4847
import org.scijava.ops.matcher.OpCandidate.StatusCode;
49-
import org.scijava.plugin.Parameter;
5048
import org.scijava.plugin.Plugin;
5149
import org.scijava.service.AbstractService;
5250
import org.scijava.service.Service;
@@ -55,18 +53,19 @@
5553
import org.scijava.util.Types.TypeVarInfo;
5654

5755
/**
58-
* Default service for finding ops which match a request.
56+
* Default implementation of {@link OpMatcher}. Used for finding Ops which match
57+
* a {@link OpRef request}.
5958
*
6059
* @author David Kolb
6160
*/
6261
@Plugin(type = Service.class)
63-
public class DefaultOpTypeMatchingService extends AbstractService implements OpTypeMatchingService {
62+
public class DefaultOpMatcher extends AbstractService implements OpMatcher {
6463

65-
@Parameter
66-
private Context context;
64+
private final Logger log;
6765

68-
@Parameter
69-
private LogService log;
66+
public DefaultOpMatcher(final Logger log) {
67+
this.log = log;
68+
}
7069

7170
@Override
7271
public OpCandidate findSingleMatch(final OpEnvironment ops, final OpRef ref) throws OpMatchingException {
@@ -155,7 +154,7 @@ public boolean typesMatch(final OpCandidate candidate) {
155154
* Performs several checks, whether the specified candidate:</br>
156155
* </br>
157156
* * {@link #isValid(OpCandidate)}</br>
158-
* * {@link #outputsMatch(OpCandidate)}</br>
157+
* * {@link #outputsMatch(OpCandidate, HashMap)}</br>
159158
* * has a matching number of args</br>
160159
* * {@link #missArgs(OpCandidate, Type[])}</br>
161160
* </br>

src/main/java/org/scijava/ops/matcher/MatchingResult.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
/**
99
* Class representing the result from type matching done by the
10-
* {@link OpTypeMatchingService}. Contains the original candidates which match
10+
* {@link OpMatcher}. Contains the original candidates which match
1111
* the types specified by {@link OpRef} and the final matches that match all
1212
* inputs, outputs, and arguments.
1313
*

src/main/java/org/scijava/ops/matcher/OpCandidate.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@
4444

4545
/**
4646
* Container class for a possible operation match between an {@link OpRef} and
47-
* an {@link OpInfo}, as computed by the {@link OpTypeMatchingService}.
47+
* an {@link OpInfo}, as computed by the {@link OpMatcher}.
4848
*
4949
* @author Curtis Rueden
50-
* @see OpTypeMatchingService
50+
* @see OpMatcher
5151
*/
5252
public class OpCandidate {
5353

src/main/java/org/scijava/ops/matcher/OpTypeMatchingService.java renamed to src/main/java/org/scijava/ops/matcher/OpMatcher.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,17 @@
3232
import java.util.List;
3333

3434
import org.scijava.ops.OpEnvironment;
35-
import org.scijava.service.SciJavaService;
3635

3736
/**
38-
* Interface for services that find ops which match an {@link OpRef}.
39-
*
37+
* Finds Ops which match an {@link OpRef}.
38+
*
4039
* @author Curtis Rueden
4140
*/
4241
//TODO javadoc
43-
public interface OpTypeMatchingService extends SciJavaService {
42+
public interface OpMatcher {
43+
44+
OpCandidate findSingleMatch(OpEnvironment ops, OpRef ref) throws OpMatchingException;
4445

45-
OpCandidate findSingleMatch(final OpEnvironment ops, final OpRef ref) throws OpMatchingException;
46-
4746
MatchingResult findMatch(OpEnvironment ops, OpRef ref);
4847

4948
MatchingResult findMatch(OpEnvironment ops, List<OpRef> refs);

src/main/java/org/scijava/ops/matcher/OpRef.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
* Data structure which identifies an op by name and/or type(s) and/or argument
4545
* type(s), along with a list of input arguments.
4646
* <p>
47-
* With the help of the {@link OpTypeMatchingService}, an {@code OpRef} holds all
47+
* With the help of the {@link OpMatcher}, an {@code OpRef} holds all
4848
* information needed to create an appropriate {@link Op}.
4949
* </p>
5050
*

src/main/java/org/scijava/ops/transform/DefaultOpTransformerService.java renamed to src/main/java/org/scijava/ops/transform/DefaultOpTransformationMatcher.java

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,34 +40,31 @@
4040

4141
import org.scijava.ops.OpEnvironment;
4242
import org.scijava.ops.matcher.OpCandidate;
43+
import org.scijava.ops.matcher.OpMatcher;
4344
import org.scijava.ops.matcher.OpMatchingException;
4445
import org.scijava.ops.matcher.OpRef;
45-
import org.scijava.ops.matcher.OpTypeMatchingService;
46-
import org.scijava.plugin.AbstractSingletonService;
47-
import org.scijava.plugin.Parameter;
48-
import org.scijava.plugin.Plugin;
49-
import org.scijava.service.Service;
5046

5147
/**
52-
* Default service to find Op transformations. This default service will chain two transformations
53-
* at maximum.
54-
*
48+
* Default implementation of {@link OpTransformationMatcher}. This
49+
* implementation will chain two transformations at maximum.
50+
*
5551
* @author David Kolb
5652
*/
57-
@Plugin(type = Service.class)
58-
public final class DefaultOpTransformerService extends AbstractSingletonService<OpTransformer>
59-
implements OpTransformerService {
53+
public class DefaultOpTransformationMatcher implements OpTransformationMatcher {
54+
55+
private final OpMatcher matcher;
6056

61-
@Parameter
62-
private OpTypeMatchingService matcher;
63-
6457
private final int maxTransformations = 2;
6558

59+
public DefaultOpTransformationMatcher(final OpMatcher matcher) {
60+
this.matcher = matcher;
61+
}
62+
6663
@Override
67-
public List<OpTransformation> getTransformationsTo(OpRef toRef, int currentChainLength) {
64+
public List<OpTransformation> getTransformationsTo(final Iterable<OpTransformer> transformers, OpRef toRef, int currentChainLength) {
6865
List<OpTransformation> transforms = new ArrayList<>();
6966

70-
for (OpTransformer ot: getInstances()) {
67+
for (OpTransformer ot: transformers) {
7168
final Collection<OpRef> fromRefs = ot.getRefsTransformingTo(toRef);
7269
if (fromRefs != null) {
7370
for (OpRef fromRef : fromRefs) {
@@ -79,11 +76,11 @@ public List<OpTransformation> getTransformationsTo(OpRef toRef, int currentChain
7976
}
8077
return transforms;
8178
}
82-
79+
8380
@Override
84-
public OpTransformationCandidate findTransformation(OpEnvironment opEnv, OpRef ref) {
81+
public OpTransformationCandidate findTransformation(OpEnvironment opEnv, final Iterable<OpTransformer> transformers, OpRef ref) {
8582
LinkedList<OpTransformation> tsQueue = new LinkedList<>();
86-
tsQueue.addAll(getTransformationsTo(ref, 0));
83+
tsQueue.addAll(getTransformationsTo(transformers, ref, 0));
8784
while (!tsQueue.isEmpty()) {
8885
OpTransformation t = tsQueue.pop();
8986
OpRef fromRef = t.getSource();
@@ -96,7 +93,7 @@ public OpTransformationCandidate findTransformation(OpEnvironment opEnv, OpRef r
9693
if (t.getChainLength() < maxTransformations)
9794
// we need to make sure chain all of these transformations to t, thus we map the
9895
// results of getTransformationsTo
99-
tsQueue.addAll(getTransformationsTo(fromRef, t.getChainLength())//
96+
tsQueue.addAll(getTransformationsTo(transformers, fromRef, t.getChainLength())//
10097
.stream().map(next -> next.chain(t))//
10198
.collect(Collectors.toList()));
10299
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
package org.scijava.ops.transform;
3+
4+
import java.util.List;
5+
6+
import org.scijava.ops.OpEnvironment;
7+
import org.scijava.ops.matcher.OpRef;
8+
9+
/**
10+
* Matches {@link OpTransformer}s that transform {@link OpRef}s and Ops.
11+
*
12+
* @author David Kolb
13+
*/
14+
public interface OpTransformationMatcher {
15+
16+
/**
17+
* Retrieve a list of {@link OpTransformation}s that describe a transformation
18+
* that is able to transform an Op matching an {@link OpRef} into another Op
19+
* matching the specified {@link OpRef}. This can be used to find Ops that are
20+
* transformable into the specified {@link OpRef}.
21+
*
22+
* @param opRef the ref which should be the target of the transformations to
23+
* look for
24+
*/
25+
List<OpTransformation> getTransformationsTo(Iterable<OpTransformer> transformers, OpRef opRef, int currentChainLength);
26+
27+
/**
28+
* Attempts to find an {@link OpTransformationCandidate}, transforming an
29+
* existing Op into another Op that matches the specified {@link OpRef}. This
30+
* can be used if no Op matching the specified ref is available, however there
31+
* are Op transformations that are able to transform an existing Op into the
32+
* requested one. E.g. a Computer is requested, however there is only a
33+
* Function operating on the same types and a transformer from Function to
34+
* Computer available. Hence, one can take the available Function and
35+
* transform it into the requested Computer and return it.
36+
*
37+
* @param opEnv the env to supply ops
38+
* @param ref the ref which should be the target of the transformation to look
39+
* for
40+
*/
41+
OpTransformationCandidate findTransformation(OpEnvironment opEnv, Iterable<OpTransformer> transformers, OpRef ref);
42+
}

0 commit comments

Comments
 (0)