/**
  * Dependencies are satisfied if the latestRevision is at least the latestRevision of all
  * upstream {@link DependentSubjectListener}s.
  */
 public void assertDependenciesSatisfiedRecursively(DetachedSubject notified) {
   final Iterator<DetachedSubject> iter = upstreamSubjects.iterator();
   while (iter.hasNext()) {
     final DetachedSubject upstream = iter.next();
     upstream.assertDependenciesSatisfiedRecursively(notified);
     if (latestRevision < upstream.latestRevision) {
       throw new IllegalStateException(
           "Dependencies not satisfied for "
               + notified
               + ", dependency "
               + this
               + " not updated by "
               + upstream
               + "!");
     }
   }
 }
 public void fire(DetachedSubject subject, Integer event, DetachedSubject.Listener listener) {
   boolean changed = listener.subject.latestRevision < event.intValue();
   // update the listener
   listener.subject.latestRevision = event.intValue();
   // make sure the listener's dependencies were notified first
   listener.subject.assertDependenciesSatisfiedRecursively(listener.subject);
   // send the event forward
   if (changed) listener.subject.increment(0);
 }
  /**
   * Test that listeners and subjects do not have to use the same identity so long as {@link
   * ListEventPublisher#setRelatedSubject} is used.
   */
  public void testRelatedSubjects() {
    SequenceDependenciesEventPublisher publisher = new SequenceDependenciesEventPublisher();
    DetachedSubject a = new DetachedSubject("A", publisher);
    DetachedSubject b = new DetachedSubject("B", publisher);
    DetachedSubject c = new DetachedSubject("C", publisher);
    DetachedSubject d = new DetachedSubject("D", publisher);
    DetachedSubject e = new DetachedSubject("E", publisher);

    b.addListener(e);
    a.addListener(b);

    c.addListener(e);
    a.addListener(c);

    d.addListener(e);
    a.addListener(d);

    // changing a should impact e, but only after b, c, and d
    a.increment(10);
    assertEquals(10, a.latestRevision);
    assertEquals(10, b.latestRevision);
    assertEquals(10, c.latestRevision);
    assertEquals(10, d.latestRevision);
    assertEquals(10, e.latestRevision);
  }