/**
  * Organized the Applications of "d" into a leveled data structure based on their dependance among
  * each other
  *
  * @return exactly the same Application instances in a leveled data structure
  */
 private final List<Set<Rule.Match>> getTopology(List<Rule.Match> l) {
   List<Set<Occurrence>> levels = new ArrayList<Set<Occurrence>>();
   Occurrence initialWord = new Occurrence();
   initialWord.setSymbol(l.get(0).rule.getLeftHandSide().get(0));
   initialWord.setSource(null);
   initialWord.setPosition(0);
   ensureCapacity(1, levels);
   levels.get(0).add(initialWord);
   List<Occurrence> currentWord = new ArrayList<Occurrence>();
   currentWord.add(initialWord);
   for (int i = 0; i < l.size(); i++) {
     Rule.Match a = l.get(i);
     List<Occurrence> depSeq = dependingSubsequence(currentWord, a);
     List<Occurrence> newWord = apply(currentWord, a);
     List<Occurrence> prodSeq = producedSubsequence(newWord, a);
     int myLevel = getMaxLevel(depSeq, levels) + 1;
     ensureCapacity(myLevel + 1, levels);
     Set<Occurrence> myLevelSet = levels.get(myLevel);
     myLevelSet.addAll(prodSeq);
     currentWord = newWord;
   }
   List<Set<Rule.Match>> result = new ArrayList<Set<Rule.Match>>();
   for (Set<Occurrence> level : levels) {
     Set<Rule.Match> set = new HashSet<Rule.Match>();
     result.add(set);
     for (Occurrence o : level) {
       set.add(o.getSource());
     }
   }
   return result;
 }
 /**
  * applies "a" to the "word".
  *
  * @return the resulting word
  */
 private final List<Occurrence> apply(List<Occurrence> word, Rule.Match a) {
   Rule r = a.rule;
   int length = word.size() - r.getLeftHandSide().length() + r.getRightHandSide().length();
   int pos = a.leftHandSideStart;
   List<Occurrence> result = new ArrayList<Occurrence>(length);
   int rp = 0;
   for (; rp < pos; rp++) {
     result.add(word.get(rp));
   }
   Occurrence sourceOcc = word.get(rp + 1);
   for (int i = 0; rp < pos + r.getRightHandSide().length(); rp++, i++) {
     Occurrence o = new Occurrence();
     o.setSymbol(r.getRightHandSide().get(i));
     o.setSourceOccurrence(sourceOcc);
     o.setPosition(rp);
     o.setSource(a);
     result.add(o);
   }
   for (int sp = pos + r.getLeftHandSide().length(); sp < word.size(); rp++, sp++) {
     result.add(word.get(sp));
   }
   return result;
 }