/** * 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); }