Program: 32642
Project: 32642
Buggy source:
/** 
 * Rebuild the subject and listeners list so that all required invariants are met with respect to notification order. That is, for any listener T, all of the subjects S that T listens to have been updated before T receives a change event from any S. <p>This implementation still has some problems and work left to do: <li>it's big! Can we optimize it? Perhaps shortcutting all the graph work for simple cases (the 99% case) <li>it's complex! Can we simplify it? <li>could we keep the datastructures around? it may be wasteful to reconstruct them every single time a listener is changed
 */
private List<SubjectAndListener> orderSubjectsAndListeners(List<SubjectAndListener> subjectsAndListeners){
  List<SubjectAndListener> result=new ArrayList<SubjectAndListener>();
  IdentityMultimap<Object,SubjectAndListener> sourceToPairs=new IdentityMultimap<Object,SubjectAndListener>();
  IdentityMultimap<Object,SubjectAndListener> targetToPairs=new IdentityMultimap<Object,SubjectAndListener>();
  Map<Object,Boolean> satisfied=new IdentityHashMap<Object,Boolean>();
  List<Object> satisfiedToDo=new ArrayList<Object>();
  for (int i=0, size=subjectsAndListeners.size(); i < size; i++) {
    SubjectAndListener subjectAndListener=subjectsAndListeners.get(i);
    Object source=subjectAndListener.subject;
    Object target=getRelatedSubject(subjectAndListener.listener);
    sourceToPairs.addValue(source,subjectAndListener);
    targetToPairs.addValue(target,subjectAndListener);
    satisfied.remove(target);
    if (targetToPairs.count(source) == 0) {
      satisfied.put(source,Boolean.TRUE);
    }
  }
  satisfiedToDo.addAll(satisfied.keySet());
  while (!satisfiedToDo.isEmpty()) {
    Object subject=satisfiedToDo.remove(0);
    List<SubjectAndListener> sourceTargets=sourceToPairs.get(subject);
    tryEachTarget:     for (int t=0, targetsSize=sourceTargets.size(); t < targetsSize; t++) {
      Object sourceTarget=getRelatedSubject(sourceTargets.get(t).listener);
      List<SubjectAndListener> allSourcesForSourceTarget=targetToPairs.get(sourceTarget);
      if (allSourcesForSourceTarget.size() == 0)       continue;
      for (int s=0, sourcesSize=allSourcesForSourceTarget.size(); s < sourcesSize; s++) {
        SubjectAndListener sourceAndTarget=allSourcesForSourceTarget.get(s);
        if (!satisfied.containsKey(sourceAndTarget.subject)) {
          continue tryEachTarget;
        }
      }
      result.addAll(allSourcesForSourceTarget);
      targetToPairs.remove(sourceTarget);
      satisfiedToDo.add(sourceTarget);
      satisfied.put(sourceTarget,Boolean.TRUE);
    }
  }
  if (!targetToPairs.isEmpty()) {
    throw new IllegalStateException("String_Node_Str" + targetToPairs.values());
  }
  return result;
}

Fixed version (ground truth):
/** 
 * Rebuild the subject and listeners list so that all required invariants are met with respect to notification order. That is, for any listener T, all of the subjects S that T listens to have been updated before T receives a change event from any S. <p>This implementation still has some problems and work left to do: <li>it's big! Can we optimize it? Perhaps shortcutting all the graph work for simple cases (the 99% case) <li>it's complex! Can we simplify it? <li>could we keep the datastructures around? it may be wasteful to reconstruct them every single time a listener is changed
 */
private List<SubjectAndListener> orderSubjectsAndListeners(List<SubjectAndListener> subjectsAndListeners){
  List<SubjectAndListener> result=new ArrayList<SubjectAndListener>();
  IdentityMultimap<Object,SubjectAndListener> sourceToPairs=new IdentityMultimap<Object,SubjectAndListener>();
  IdentityMultimap<Object,SubjectAndListener> targetToPairs=new IdentityMultimap<Object,SubjectAndListener>();
  Map<Object,Boolean> satisfied=new IdentityHashMap<Object,Boolean>();
  List<Object> satisfiedToDo=new ArrayList<Object>();
  for (int i=0, size=subjectsAndListeners.size(); i < size; i++) {
    SubjectAndListener subjectAndListener=subjectsAndListeners.get(i);
    Object source=subjectAndListener.subject;
    Object target=getRelatedSubject(subjectAndListener.listener);
    sourceToPairs.addValue(source,subjectAndListener);
    targetToPairs.addValue(target,subjectAndListener);
    satisfied.remove(target);
    if (targetToPairs.count(source) == 0) {
      satisfied.put(source,Boolean.TRUE);
    }
  }
  satisfiedToDo.addAll(satisfied.keySet());
  while (!satisfiedToDo.isEmpty()) {
    Object subject=satisfiedToDo.remove(0);
    List<SubjectAndListener> sourceTargets=(List<SubjectAndListener>)sourceToPairs.get(subject);
    tryEachTarget:     for (int t=0, targetsSize=sourceTargets.size(); t < targetsSize; t++) {
      Object sourceTarget=getRelatedSubject(sourceTargets.get(t).listener);
      List<SubjectAndListener> allSourcesForSourceTarget=(List<SubjectAndListener>)targetToPairs.get(sourceTarget);
      if (allSourcesForSourceTarget.size() == 0)       continue;
      for (int s=0, sourcesSize=allSourcesForSourceTarget.size(); s < sourcesSize; s++) {
        SubjectAndListener sourceAndTarget=allSourcesForSourceTarget.get(s);
        if (!satisfied.containsKey(sourceAndTarget.subject)) {
          continue tryEachTarget;
        }
      }
      result.addAll(allSourcesForSourceTarget);
      targetToPairs.remove(sourceTarget);
      satisfiedToDo.add(sourceTarget);
      satisfied.put(sourceTarget,Boolean.TRUE);
    }
  }
  if (!targetToPairs.isEmpty()) {
    throw new IllegalStateException("String_Node_Str" + targetToPairs.values());
  }
  return result;
}