2929package org .scijava .ops ;
3030
3131import java .lang .reflect .Field ;
32- import java .lang .reflect .InvocationTargetException ;
3332import java .lang .reflect .Modifier ;
3433import java .lang .reflect .Type ;
3534import java .lang .reflect .TypeVariable ;
4847import org .scijava .log .LogService ;
4948import org .scijava .ops .core .Op ;
5049import org .scijava .ops .core .OpCollection ;
51- import org .scijava .ops .function .GenericTypedOp ;
5250import org .scijava .ops .matcher .DefaultOpMatcher ;
5351import org .scijava .ops .matcher .OpCandidate ;
5452import org .scijava .ops .matcher .OpClassInfo ;
6664import org .scijava .ops .types .Any ;
6765import org .scijava .ops .types .Nil ;
6866import org .scijava .ops .types .TypeService ;
67+ import org .scijava .ops .util .OpWrapper ;
6968import org .scijava .param .FunctionalMethodType ;
7069import org .scijava .param .ParameterStructs ;
7170import org .scijava .plugin .Parameter ;
@@ -104,7 +103,7 @@ public class OpService extends AbstractService implements SciJavaService, OpEnvi
104103 /**
105104 * Prefix tree to cache and quickly find {@link OpInfo}s.
106105 */
107- // private PrefixTree<OpInfo> opCache;
106+ // private PrefixTree<OpInfo> opCache;
108107
109108 /**
110109 * Map to collect all aliases for a specific op. All aliases will map to one
@@ -114,33 +113,9 @@ public class OpService extends AbstractService implements SciJavaService, OpEnvi
114113
115114 private List <OpTransformer > transformerIndex ;
116115
117- private static Map <Class <?>, Class <?>> wrappers = wrappers ();
118-
119- private static Map <Class <?>, Class <?>> wrappers () {
120- final Map <Class <?>, Class <?>> result = new HashMap <>();
121- final Class <?>[] wrapperClasses = { //
122- GenericTypedOp .P .class , //
123- GenericTypedOp .F1 .class , //
124- GenericTypedOp .F2 .class , //
125- GenericTypedOp .F3 .class , //
126- GenericTypedOp .C0 .class , //
127- GenericTypedOp .C1 .class , //
128- GenericTypedOp .C2 .class , //
129- GenericTypedOp .C3 .class , //
130- GenericTypedOp .IP1 .class , //
131- GenericTypedOp .IP2_1 .class , //
132- GenericTypedOp .IP2_2 .class , //
133- GenericTypedOp .IP3_1 .class , //
134- GenericTypedOp .IP3_2 .class , //
135- GenericTypedOp .IP3_3 .class //
136- };
137- for (final Class <?> c : wrapperClasses ) {
138- result .put (c .getInterfaces ()[0 ], c );
139- }
140- return result ;
141- }
116+ private Map <Class <?>, OpWrapper <?>> wrappers ;
142117
143- public void initOpCache () {
118+ private void initOpCache () {
144119 opCache = new HashMap <>();
145120
146121 // Add regular Ops
@@ -158,7 +133,7 @@ public void initOpCache() {
158133 try {
159134 Class <? extends OpCollection > c = pluginInfo .loadClass ();
160135 final List <Field > fields = ClassUtils .getAnnotatedFields (c , OpField .class );
161- Object instance = null ;
136+ Object instance = null ;
162137 for (Field field : fields ) {
163138 final boolean isStatic = Modifier .isStatic (field .getModifiers ());
164139 if (!isStatic && instance == null ) {
@@ -173,6 +148,13 @@ public void initOpCache() {
173148 }
174149 }
175150
151+ private void initWrappers () {
152+ wrappers = new HashMap <>();
153+ for (OpWrapper <?> wrapper : pluginService .createInstancesOfType (OpWrapper .class )) {
154+ wrappers .put (wrapper .type (), wrapper );
155+ }
156+ }
157+
176158 private void addToOpIndex (final OpInfo opInfo , final String opNames ) {
177159 String [] parsedOpNames = OpUtils .parseOpNames (opNames );
178160 if (parsedOpNames == null || parsedOpNames .length == 0 ) {
@@ -184,7 +166,7 @@ private void addToOpIndex(final OpInfo opInfo, final String opNames) {
184166 + opInfo .getValidityException ().getMessage ());
185167 return ;
186168 }
187- for (String opName : parsedOpNames ) {
169+ for (String opName : parsedOpNames ) {
188170 if (!opCache .containsKey (opName ))
189171 opCache .put (opName , new ArrayList <>());
190172 opCache .get (opName ).add (opInfo );
@@ -200,9 +182,7 @@ public Iterable<OpInfo> infos() {
200182 if (opCache == null ) {
201183 initOpCache ();
202184 }
203- return opCache .values ().stream ()
204- .flatMap (list -> list .stream ())
205- .collect (Collectors .toList ());
185+ return opCache .values ().stream ().flatMap (list -> list .stream ()).collect (Collectors .toList ());
206186 }
207187
208188 @ Override
@@ -251,30 +231,23 @@ private OpTransformationMatcher getTransformationMatcher() {
251231 * matching the functional type and the name could not be found, if
252232 * an exception occurs during injection
253233 */
254- private List <Object > resolveOpDependencies (OpCandidate op )
255- throws OpMatchingException
256- {
234+ private List <Object > resolveOpDependencies (OpCandidate op ) throws OpMatchingException {
257235 final List <OpDependencyMember <?>> dependencies = op .opInfo ().dependencies ();
258- final List <Object > resolvedDependencies = new ArrayList <>(dependencies
259- .size ());
236+ final List <Object > resolvedDependencies = new ArrayList <>(dependencies .size ());
260237 for (final OpDependencyMember <?> dependency : dependencies ) {
261238 final String dependencyName = dependency .getDependencyName ();
262- final Type mappedDependencyType = Types .mapVarToTypes (new Type [] {
263- dependency .getType () }, op .typeVarAssigns ())[0 ];
264- final OpRef inferredRef = inferOpRef (mappedDependencyType , dependencyName ,
265- op .typeVarAssigns ());
239+ final Type mappedDependencyType = Types .mapVarToTypes (new Type [] { dependency .getType () },
240+ op .typeVarAssigns ())[0 ];
241+ final OpRef inferredRef = inferOpRef (mappedDependencyType , dependencyName , op .typeVarAssigns ());
266242 if (inferredRef == null ) {
267- throw new OpMatchingException ("Could not infer functional " +
268- "method inputs and outputs of Op dependency field: " + dependency
269- .getKey ());
243+ throw new OpMatchingException ("Could not infer functional "
244+ + "method inputs and outputs of Op dependency field: " + dependency .getKey ());
270245 }
271246 try {
272247 resolvedDependencies .add (findOpInstance (dependencyName , inferredRef ));
273- }
274- catch (final Exception e ) {
275- throw new OpMatchingException (
276- "Could not find Op that matches requested Op dependency:" +
277- "\n Op class: " + op .opInfo ().implementationName () + //
248+ } catch (final Exception e ) {
249+ throw new OpMatchingException ("Could not find Op that matches requested Op dependency:" + "\n Op class: "
250+ + op .opInfo ().implementationName () + //
278251 "\n Dependency identifier: " + dependency .getKey () + //
279252 "\n \n Attempted request:\n " + inferredRef , e );
280253 }
@@ -285,8 +258,8 @@ private List<Object> resolveOpDependencies(OpCandidate op)
285258 @ SuppressWarnings ("unchecked" )
286259 public <T > T findOpInstance (final String opName , final Nil <T > specialType , final Nil <?>[] inTypes ,
287260 final Nil <?> outType ) {
288- final OpRef ref = OpRef .fromTypes (opName , toTypes (specialType ), outType != null ? outType .getType () : null , toTypes (
289- inTypes ));
261+ final OpRef ref = OpRef .fromTypes (opName , toTypes (specialType ), outType != null ? outType .getType () : null ,
262+ toTypes ( inTypes ));
290263 return (T ) findOpInstance (opName , ref );
291264 }
292265
@@ -314,8 +287,7 @@ public Object findOpInstance(final String opName, final OpRef ref) {
314287 // If we found one, try to do transformation and return transformed op
315288 log .debug ("Matching Op transformation found:\n " + transformation + "\n " );
316289 try {
317- final List <Object > dependencies = resolveOpDependencies (transformation
318- .getSourceOp ());
290+ final List <Object > dependencies = resolveOpDependencies (transformation .getSourceOp ());
319291 op = transformation .exceute (this , dependencies );
320292 } catch (OpMatchingException | OpTransformationException e1 ) {
321293 throw new IllegalArgumentException ("Execution of Op transformatioon failed:\n " + e1 );
@@ -349,8 +321,12 @@ else if (transformation != null)
349321 * @return an {@link Op} wrapping of op.
350322 */
351323 private Object wrapOp (Object op , OpCandidate match , OpTransformationCandidate transformation ) {
324+ if (wrappers == null )
325+ initWrappers ();
326+
352327 // TODO: we don't want to wrap OpRunners, do we? What is the point?
353- if (OpRunner .class .isInstance (op )) return op ;
328+ if (OpRunner .class .isInstance (op ))
329+ return op ;
354330
355331 OpInfo opInfo = match == null ? transformation .getSourceOp ().opInfo () : match .opInfo ();
356332 // FIXME: this type is not necessarily Computer, Function, etc. but often
@@ -367,12 +343,8 @@ private Object wrapOp(Object op, OpCandidate match, OpTransformationCandidate tr
367343 throw new IllegalArgumentException (
368344 "Matched op Type " + type .getClass () + " matches multiple Op types: " + wrappers .toString ());
369345 // get the wrapper and wrap up the Op
370- Class <?> wrapper = wrappers .get (suitableWrappers [0 ]);
371- // CTR FIXME: Instead of using reflection, register constructors
372- // as BiFunction<OP, OpInfo, GenericOp<OP>> via ::new syntax.
373- return wrapper .getConstructors ()[0 ].newInstance (op , opInfo );
374- } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
375- | SecurityException exc ) {
346+ return wrap (suitableWrappers [0 ], op , opInfo );
347+ } catch (IllegalArgumentException | SecurityException exc ) {
376348 log .error (exc .getMessage () != null ? exc .getMessage () : "Cannot wrap " + op .getClass ());
377349 return op ;
378350 } catch (NullPointerException e ) {
@@ -381,6 +353,12 @@ private Object wrapOp(Object op, OpCandidate match, OpTransformationCandidate tr
381353 }
382354 }
383355
356+ @ SuppressWarnings ("unchecked" )
357+ private <T > T wrap (Class <T > opType , Object op , OpInfo info ) {
358+ OpWrapper <T > wrapper = (OpWrapper <T >) wrappers .get (opType );
359+ return wrapper .wrap ((T ) op , info );
360+ }
361+
384362 public <T > T findOp (final String opName , final Nil <T > specialType , final Nil <?>[] inTypes , final Nil <?> outType ) {
385363 return findOpInstance (opName , specialType , inTypes , outType );
386364 }
@@ -392,9 +370,14 @@ private Type[] toTypes(Nil<?>... nils) {
392370 public Object run (final String opName , final Object ... args ) {
393371
394372 Nil <?>[] inTypes = Arrays .stream (args ).map (arg -> Nil .of (typeService .reify (arg ))).toArray (Nil []::new );
395- Nil <?> outType = new Nil <Any >() { @ Override public Type getType () {return new Any ();}};
373+ Nil <?> outType = new Nil <Any >() {
374+ @ Override
375+ public Type getType () {
376+ return new Any ();
377+ }
378+ };
396379
397- OpRunner op = findOpInstance (opName , new Nil <OpRunner >(){}, inTypes , outType );
380+ OpRunner op = findOpInstance (opName , new Nil <OpRunner >() {}, inTypes , outType );
398381 return op .run (args );
399382 }
400383
@@ -413,6 +396,7 @@ public Object run(final String opName, final Object... args) {
413396 * InputTypes: [Double[], Double[]]
414397 * OutputTypes: [Double[]]
415398 * </pre>
399+ *
416400 * Input and output types will be inferred by looking at the signature of the
417401 * functional method of the specified type. Also see
418402 * {@link ParameterStructs#findFunctionalMethodTypes(Type)}.
@@ -422,8 +406,7 @@ public Object run(final String opName, final Object... args) {
422406 * @return null if the specified type has no functional method
423407 */
424408 private OpRef inferOpRef (Type type , String name , Map <TypeVariable <?>, Type > typeVarAssigns )
425- throws OpMatchingException
426- {
409+ throws OpMatchingException {
427410 List <FunctionalMethodType > fmts = ParameterStructs .findFunctionalMethodTypes (type );
428411 if (fmts == null )
429412 return null ;
@@ -444,8 +427,8 @@ private OpRef inferOpRef(Type type, String name, Map<TypeVariable<?>, Type> type
444427 if (numOutputs != 1 ) {
445428 String error = "Op '" + name + "' of type " + type + " specifies " ;
446429 error += numOutputs == 0 //
447- ? "no outputs" //
448- : "multiple outputs: " + Arrays .toString (outputs );
430+ ? "no outputs" //
431+ : "multiple outputs: " + Arrays .toString (outputs );
449432 error += ". This is not supported." ;
450433 throw new OpMatchingException (error );
451434 }
@@ -739,8 +722,7 @@ private String nodeToString(PrefixNode<T> node, String nodeName, StringBuilder s
739722 for (T t : node .data ) {
740723 sb .append (getIndent (level ) + "\t " + t .getClass ().getSimpleName () + "\n " );
741724 }
742- if (!node .data .isEmpty ()) {
743- } else {
725+ if (!node .data .isEmpty ()) {} else {
744726 sb .delete (sb .length () - 1 , sb .length ());
745727 sb .append (" <empty>\n " );
746728 }
@@ -751,8 +733,7 @@ private String nodeToString(PrefixNode<T> node, String nodeName, StringBuilder s
751733 String sub = nodeToString (e .getValue (), e .getKey (), new StringBuilder (), level + 1 );
752734 sb .append (sub + "\n " );
753735 }
754- if (!node .children .isEmpty ()) {
755- } else {
736+ if (!node .children .isEmpty ()) {} else {
756737 sb .delete (sb .length () - 1 , sb .length ());
757738 sb .append (" <empty>\n " );
758739 }
0 commit comments