@@ -91,7 +91,7 @@ public class OpService extends AbstractService implements SciJavaService, OpEnvi
9191
9292 @ Parameter
9393 private OpTransformerService transformer ;
94-
94+
9595 @ Parameter
9696 private TypeService typeService ;
9797
@@ -123,8 +123,7 @@ public void initOpCache() {
123123 // Add Ops contained in an OpCollection
124124 for (final PluginInfo <OpCollection > pluginInfo : pluginService .getPluginsOfType (OpCollection .class )) {
125125 try {
126- final List <Field > fields = ClassUtils .getAnnotatedFields (pluginInfo .loadClass (),
127- OpField .class );
126+ final List <Field > fields = ClassUtils .getAnnotatedFields (pluginInfo .loadClass (), OpField .class );
128127 for (Field field : fields ) {
129128 OpInfo opInfo = new OpFieldInfo (field );
130129 addToCache (opInfo , field .getAnnotation (OpField .class ).names ());
@@ -138,8 +137,7 @@ public void initOpCache() {
138137 private void addToCache (OpInfo opInfo , String opNames ) {
139138 String [] parsedOpNames = OpUtils .parseOpNames (opNames );
140139 if (parsedOpNames == null || parsedOpNames .length == 0 ) {
141- log .error ("Skipping Op " + opInfo .implementationName () + ":\n "
142- + "Op implementation must provide name." );
140+ log .error ("Skipping Op " + opInfo .implementationName () + ":\n " + "Op implementation must provide name." );
143141 return ;
144142 }
145143 if (!opInfo .isValid ()) {
@@ -180,53 +178,53 @@ public LogService logger() {
180178 }
181179
182180 /**
183- * Attempts to inject {@link OpDependency} annotated fields of the specified object by
184- * looking for Ops matching the field type and the name specified in the
185- * annotation. The field type is assumed to be functional.
181+ * Attempts to inject {@link OpDependency} annotated fields of the specified
182+ * object by looking for Ops matching the field type and the name specified in
183+ * the annotation. The field type is assumed to be functional.
186184 *
187185 * @param obj
188186 * @throws OpMatchingException
189- * if the type of the specified object is not functional,
190- * if the Op matching the functional type and the name could not be found,
191- * if an exception occurs during injection
187+ * if the type of the specified object is not functional, if the Op
188+ * matching the functional type and the name could not be found, if
189+ * an exception occurs during injection
192190 */
193- public void resolveOpDependencies (Object obj , OpCandidate parentOp ) throws OpMatchingException {
194- final Class <?> c = obj .getClass ();
195- final List <Field > opFields = ClassUtils .getAnnotatedFields (c , OpDependency .class );
191+ private void resolveOpDependencies (Object obj , OpCandidate parentOp ) throws OpMatchingException {
192+ Object op = obj ;
193+ // HACK: Only works with Op instances and OpRunner, not extensible.
194+ // Consider extensible ways to achieve something similar e.g. extending OpInfo
195+ // to support OpDependencies.
196+ if (obj instanceof OpRunner ) {
197+ op = ((OpRunner ) obj ).getAdaptedOp ();
198+ }
199+ final List <Field > opFields = ClassUtils .getAnnotatedFields (op .getClass (), OpDependency .class );
196200
197201 for (final Field opField : opFields ) {
198202 final String opName = opField .getAnnotation (OpDependency .class ).name ();
199- final Type fieldType = Types .fieldType (opField , c );
200- final Type mappedFieldType = Types .mapVarToTypes (new Type [] {fieldType }, parentOp .typeVarAssigns ())[0 ];
203+ final Type fieldType = Types .fieldType (opField , op . getClass () );
204+ final Type mappedFieldType = Types .mapVarToTypes (new Type [] { fieldType }, parentOp .typeVarAssigns ())[0 ];
201205
202206 OpRef inferredRef = inferOpRef (mappedFieldType , opName , parentOp .typeVarAssigns ());
203207 if (inferredRef == null ) {
204- throw new OpMatchingException ("Could not infer functional "
205- + "method inputs and outputs of Op dependency field: "
206- + opField );
208+ throw new OpMatchingException (
209+ "Could not infer functional " + "method inputs and outputs of Op dependency field: " + opField );
207210 }
208211
209212 Object matchedOp = null ;
210213 try {
211214 matchedOp = findOpInstance (opName , inferredRef );
212215 } catch (Exception e ) {
213- throw new OpMatchingException (
214- "Could not find Op that matches requested Op dependency field:"
215- + "\n Op class: " + c .getName ()
216- + "\n Dependency field: " + opField .getName ()
217- + "\n \n Attempted request:\n "
218- + inferredRef , e );
216+ throw new OpMatchingException ("Could not find Op that matches requested Op dependency field:"
217+ + "\n Op class: " + op .getClass ().getName () + "\n Dependency field: " + opField .getName ()
218+ + "\n \n Attempted request:\n " + inferredRef , e );
219219 }
220220
221221 try {
222222 opField .setAccessible (true );
223- opField .set (obj , matchedOp );
223+ opField .set (op , matchedOp );
224224 } catch (IllegalArgumentException | IllegalAccessException e ) {
225- throw new OpMatchingException (
226- "Exception trying to inject Op dependency field.\n "
227- + "\t Op dependency field to resolve: " + opField + "\n "
228- + "\t Found Op to inject: " + matchedOp .getClass ().getName () + "\n "
229- + "\t With inferred OpRef: " + inferredRef , e );
225+ throw new OpMatchingException ("Exception trying to inject Op dependency field.\n "
226+ + "\t Op dependency field to resolve: " + opField + "\n " + "\t Found Op to inject: "
227+ + matchedOp .getClass ().getName () + "\n " + "\t With inferred OpRef: " + inferredRef , e );
230228 }
231229 }
232230 }
@@ -241,6 +239,7 @@ public <T> T findOpInstance(final String opName, final Nil<T> specialType, final
241239 public Object findOpInstance (final String opName , final OpRef ref , final Object ... secondaryArgs ) {
242240 Object op = null ;
243241 OpCandidate match = null ;
242+ OpTransformationCandidate transformation = null ;
244243 try {
245244 // Find single match which matches the specified types
246245 match = matcher .findSingleMatch (this , ref );
@@ -249,8 +248,9 @@ public Object findOpInstance(final String opName, final OpRef ref, final Object.
249248 log .debug ("No matching Op for request: " + ref + "\n " );
250249 log .debug ("Attempting Op transformation..." );
251250
252- // If we can't find an op matching the original request, we try to find a transformation
253- OpTransformationCandidate transformation = transformer .findTransfromation (this , ref );
251+ // If we can't find an op matching the original request, we try to find a
252+ // transformation
253+ transformation = transformer .findTransfromation (this , ref );
254254 if (transformation == null ) {
255255 log .debug ("No matching Op transformation found" );
256256 throw new IllegalArgumentException (e );
@@ -268,7 +268,10 @@ public Object findOpInstance(final String opName, final OpRef ref, final Object.
268268 }
269269 try {
270270 // Try to resolve annotated OpDependency fields
271- resolveOpDependencies (op , match );
271+ if (match != null )
272+ resolveOpDependencies (op , match );
273+ else if (transformation != null )
274+ resolveOpDependencies (op , transformation .getSourceOp ());
272275 } catch (OpMatchingException e ) {
273276 throw new IllegalArgumentException (e );
274277 }
@@ -280,69 +283,75 @@ public <T> T findOp(final String opName, final Nil<T> specialType, final Nil<?>[
280283 return findOpInstance (opName , specialType , inTypes , outTypes , secondaryArgs );
281284 }
282285
283- public <T > T findOp (final String opName , final Nil <T > specialType , final Nil <?>[] inTypes ,
284- final Nil <?> outType , final Object ... secondaryArgs ) {
286+ public <T > T findOp (final String opName , final Nil <T > specialType , final Nil <?>[] inTypes , final Nil <?> outType ,
287+ final Object ... secondaryArgs ) {
285288 return findOpInstance (opName , specialType , inTypes , new Nil [] { outType }, secondaryArgs );
286289 }
287290
288291 private Type [] toTypes (Nil <?>... nils ) {
289292 return Arrays .stream (nils ).filter (n -> n != null ).map (n -> n .getType ()).toArray (Type []::new );
290293 }
291-
292-
294+
293295 public Object run (final String opName , final Object ... args ) {
294-
296+
295297 Nil <?>[] inTypes = Arrays .stream (args ).map (arg -> Nil .of (typeService .reify (arg ))).toArray (Nil []::new );
296- Nil <?>[] outTypes = new Nil <?>[] {new Nil <Object >() {}};
297-
298- OpRunner <Object > op = findOpInstance (opName , new Nil <OpRunner <Object >>() {}, inTypes , outTypes );
299-
300- //TODO change
298+ Nil <?>[] outTypes = new Nil <?>[] { new Nil <Object >() {
299+ } };
300+
301+ OpRunner <Object > op = findOpInstance (opName , new Nil <OpRunner <Object >>() {
302+ }, inTypes , outTypes );
303+
304+ // TODO change
301305 return op .run (args );
302306 }
303307
304308 /**
305309 * Tries to infer a {@link OpRef} from a functional Op type. E.g. the type:
306- * <pre>Computer<Double[], Double[]></pre>
310+ *
311+ * <pre>
312+ * Computer<Double[], Double[]>
313+ * </pre>
314+ *
307315 * Will result in the following {@link OpRef}:
316+ *
308317 * <pre>
309318 * Name: 'specified name'
310319 * Types: [Computer<Double, Double>]
311320 * InputTypes: [Double[], Double[]]
312321 * OutputTypes: [Double[]]
313322 * </pre>
314- * Input and output types will be inferred by looking at the signature of the functional
315- * method of the specified type. Also see {@link ParameterStructs#getFunctionalMethodTypes(Type)}.
323+ *
324+ * Input and output types will be inferred by looking at the signature of the
325+ * functional method of the specified type. Also see
326+ * {@link ParameterStructs#getFunctionalMethodTypes(Type)}.
316327 *
317328 * @param type
318329 * @param name
319- * @return null if
320- * the specified type has no functional method
330+ * @return null if the specified type has no functional method
321331 */
322332 private OpRef inferOpRef (Type type , String name , Map <TypeVariable <?>, Type > typeVarAssigns ) {
323333 List <FunctionalMethodType > fmts = ParameterStructs .getFunctionalMethodTypes (type );
324- if (fmts == null ) return null ;
334+ if (fmts == null )
335+ return null ;
325336
326337 EnumSet <ItemIO > inIos = EnumSet .of (ItemIO .BOTH , ItemIO .INPUT );
327338 EnumSet <ItemIO > outIos = EnumSet .of (ItemIO .BOTH , ItemIO .OUTPUT );
328339
329- Type [] inputs = fmts .stream ().filter (fmt -> inIos .contains (fmt .itemIO ()))
330- .map ( fmt -> fmt . type ()). toArray (Type []::new );
340+ Type [] inputs = fmts .stream ().filter (fmt -> inIos .contains (fmt .itemIO ())). map ( fmt -> fmt . type ())
341+ .toArray (Type []::new );
331342
332- Type [] outputs = fmts .stream ().filter (fmt -> outIos .contains (fmt .itemIO ()))
333- .map ( fmt -> fmt . type ()). toArray (Type []::new );
343+ Type [] outputs = fmts .stream ().filter (fmt -> outIos .contains (fmt .itemIO ())). map ( fmt -> fmt . type ())
344+ .toArray (Type []::new );
334345
335346 Type [] mappedInputs = Types .mapVarToTypes (inputs , typeVarAssigns );
336347 Type [] mappedOutputs = Types .mapVarToTypes (outputs , typeVarAssigns );
337348
338- return new OpRef (name , new Type []{ type }, mappedOutputs , mappedInputs );
349+ return new OpRef (name , new Type [] { type }, mappedOutputs , mappedInputs );
339350 }
340351
341-
342-
343352 /**
344- * Updates alias map using the specified String list. The first String in
345- * the list is assumed to be the canonical name of the op. After this method
353+ * Updates alias map using the specified String list. The first String in the
354+ * list is assumed to be the canonical name of the op. After this method
346355 * returns, all String in the specified list will map to the canonical name.
347356 *
348357 * @param opNames
@@ -355,8 +364,8 @@ private void addAliases(String[] opNames, String opImpl) {
355364 }
356365 if (opAliases .containsKey (alias )) {
357366 if (!opAliases .get (alias ).equals (opName )) {
358- log .warn ("Possible naming clash for op '" + opImpl + "' detected. Attempting to add alias '"
359- + alias + "' for op name '" + opName + "'. However the alias '" + alias + "' is already "
367+ log .warn ("Possible naming clash for op '" + opImpl + "' detected. Attempting to add alias '" + alias
368+ + "' for op name '" + opName + "'. However the alias '" + alias + "' is already "
360369 + "associated with op name '" + opAliases .get (alias ) + "'." );
361370 }
362371 continue ;
@@ -381,9 +390,9 @@ private static String getIndent(int numOfTabs) {
381390
382391 /**
383392 * Class to represent a query for a {@link PrefixTree}. Prefixes must be
384- * separated by dots ('.'). E.g. 'math.add'. These queries are used in order
385- * to specify the level where elements should be inserted into or retrieved
386- * from the tree.
393+ * separated by dots ('.'). E.g. 'math.add'. These queries are used in order to
394+ * specify the level where elements should be inserted into or retrieved from
395+ * the tree.
387396 */
388397 private static class PrefixQuery {
389398 String cachedToString ;
@@ -395,8 +404,8 @@ public static PrefixQuery all() {
395404 }
396405
397406 /**
398- * Construct a new query from the specified string. Prefixes must be
399- * separated by dots.
407+ * Construct a new query from the specified string. Prefixes must be separated
408+ * by dots.
400409 *
401410 * @param query
402411 * the string to use as query
@@ -447,8 +456,8 @@ public String toString() {
447456 }
448457
449458 /**
450- * Data structure to group elements which share common prefixes. E.g. adding
451- * the following elements:
459+ * Data structure to group elements which share common prefixes. E.g. adding the
460+ * following elements:
452461 *
453462 * <pre>
454463 * Prefix: Elem:
@@ -483,8 +492,8 @@ public PrefixTree() {
483492 }
484493
485494 /**
486- * Adds the specified element on the level represented by the specified
487- * query. This method is in O(#number of prefixes in query)
495+ * Adds the specified element on the level represented by the specified query.
496+ * This method is in O(#number of prefixes in query)
488497 *
489498 * @param query
490499 * @param node
@@ -505,13 +514,12 @@ private void add(PrefixQuery query, PrefixNode<T> node, T data) {
505514 }
506515
507516 /**
508- * Collects all elements of the level specified by the query and below.
509- * E.g. using the query 'math' on the example tree from the javadoc of
510- * this class would return all elements contained in the tree except for
511- * 'obj5'. 'math.add' would only return 'obj1' and 'obj2'. This method
512- * returns an iterable over these elements in O(# number of all nodes
513- * below query). The number of nodes is the number of distinct prefixes
514- * below the specified query.
517+ * Collects all elements of the level specified by the query and below. E.g.
518+ * using the query 'math' on the example tree from the javadoc of this class
519+ * would return all elements contained in the tree except for 'obj5'. 'math.add'
520+ * would only return 'obj1' and 'obj2'. This method returns an iterable over
521+ * these elements in O(# number of all nodes below query). The number of nodes
522+ * is the number of distinct prefixes below the specified query.
515523 *
516524 * @param query
517525 * @return
@@ -548,11 +556,11 @@ private void collectAll(PrefixNode<T> node, LinkedLinkedLists list) {
548556 }
549557
550558 /**
551- * Wrapper for {@link ArrayList}s providing O(1) concatenation of lists
552- * if only an iterator over theses lists is required. The order of lists
553- * will be retained. Added lists will be simply saved in a super
554- * LinkedList. If the iterator reaches the end of one list, it will
555- * switch to the next if available.
559+ * Wrapper for {@link ArrayList}s providing O(1) concatenation of lists if only
560+ * an iterator over theses lists is required. The order of lists will be
561+ * retained. Added lists will be simply saved in a super LinkedList. If the
562+ * iterator reaches the end of one list, it will switch to the next if
563+ * available.
556564 *
557565 * @author David Kolb
558566 */
0 commit comments