private static LinkedList<MaryModule> modulesRequiredForProcessing(MaryDataType sourceType,MaryDataType targetType,Locale locale,Voice voice,LinkedList<MaryDataType> seenTypes){
  if (sourceType.equals(targetType)) {
    Log.d(Mary.LOG,"found path through modules");
    return new LinkedList<MaryModule>();
  }
  List<MaryModule> candidates=null;
  if (voice != null)   candidates=voice.getPreferredModulesAcceptingType(sourceType);
  if (candidates == null || candidates.isEmpty()) {
    candidates=get(sourceType,locale,voice);
  }
  if (candidates == null || candidates.isEmpty()) {
    return null;
  }
  for (Iterator<MaryModule> it=candidates.iterator(); it.hasNext(); ) {
    MaryModule candidate=it.next();
    MaryDataType outputType=candidate.outputType();
    if (!seenTypes.contains(outputType)) {
      seenTypes.add(outputType);
      Log.d(Mary.LOG,"Module " + candidate.name() + " converts "+ sourceType.name()+ " into "+ outputType+ " (locale "+ locale+ ", voice "+ voice+ ")");
      LinkedList<MaryModule> path=modulesRequiredForProcessing(outputType,targetType,locale,voice,seenTypes);
      if (path != null) {
        path.addFirst(candidate);
        return path;
      }
      seenTypes.removeLast();
    }
  }
  return null;
}

private static LinkedList < MaryModule > modulesRequiredForProcessing ( MaryDataType sourceType , MaryDataType targetType , Locale locale , Voice voice , LinkedList < MaryDataType > seenTypes ) { if ( sourceType . equals ( targetType ) ) { Log . d ( Mary . LOG , "found path through modules" ) ; return new LinkedList < MaryModule > ( ) ; } List < MaryModule > candidates = null ; if ( voice != null ) candidates = voice . getPreferredModulesAcceptingType ( sourceType ) ; if ( candidates == null || candidates . isEmpty ( ) ) { candidates = get ( sourceType , locale , voice ) ; } if ( candidates == null || candidates . isEmpty ( ) ) { return null ; } for ( Iterator < MaryModule > it = candidates . iterator ( ) ; it . hasNext ( ) ; ) { MaryModule candidate = it . next ( ) ; MaryDataType outputType = candidate . outputType ( ) ; if ( ! seenTypes . contains ( outputType ) ) { seenTypes . add ( outputType ) ; Log . d ( Mary . LOG , "Module " + candidate . name ( ) + " converts " + sourceType . name ( ) + " into " + outputType + " (locale " + locale + ", voice " + voice + ")" ) ; LinkedList < MaryModule > path = modulesRequiredForProcessing ( outputType , targetType , locale , voice , seenTypes ) ; if ( path != null ) { path . addFirst ( candidate ) ; return path ; } seenTypes . removeLast ( ) ; } } return null ; }
this method recursively calls itself . it forward - constructs a list of seen types ( upon test ) , and backward - constructs a list of required modules ( upon success ) .
