Evaluating Software Design Patterns
— the "Gang of Four" patterns implemented in Java 6

dk.rode.thesis.observer
Class SequenceObserversSequence<E,A>

java.lang.Object
  extended by dk.rode.thesis.meta.model.AbstractSequence<E>
      extended by dk.rode.thesis.observer.SequenceObserversSequence<E,A>
Type Parameters:
E - The type of values delivered by this sequence.
A - The type of the aspect used by this sequence.
All Implemented Interfaces:
Sequence<E>, AspectObservable<SequenceObserver<A>,A>, AspectObservableSequence<SequenceObserver<A>,A,E>, Observable<SequenceObserver<A>>, ObservableSequence<SequenceObserver<A>,A,E>, SequenceObserver<A>, Copyable<Sequence<E>>, StrictCopyable<Sequence<E>>, Stringable<Sequence<E>>
Direct Known Subclasses:
DateSequence, SequenceObserversSequenceDecorator

@Participant(value={"Subject","Observer"})
public abstract class SequenceObserversSequence<E,A>
extends AbstractSequence<E>
implements AspectObservableSequence<SequenceObserver<A>,A,E>

A sequence observers sequence implements the basic traits of any observable sequence that uses a sequence observer as the notification mechanism.

The observable sequence functionality is fully implemented by this class! Sub-classes need simply implement the doNext() method (as opposed to next()) without worrying about notifying observers. Observers will be notified if the getAspect() method return a non-null aspect value. It is invoked immediately after doNext().

This sequence is not thread-safe! It does not enforce synchronisation, neither when adding or removing observers, nor when observers are notified. It could be potentially dangerous or least time consuming to notify observers from a synchronised context, holding a lock on the sequence itself. If synchronisation is required, the context using the sequence must enforce it.

Implementation notes:
Observable sequences inheriting this class are double as an observer: observable sequence A can add observable sequence B as an observer. The notification of observers is thus composite in a depth-first manner.

This class applies the Template Method pattern: next() is the template method, while doNext() and getAspect() are primitive operations. This ensures consistent state during notification.

Author:
Gunni Rode / rode.dk

Nested Class Summary
 
Nested classes/interfaces inherited from interface dk.rode.thesis.meta.model.Sequence
Sequence.State
 
Field Summary
private  Map<SequenceObserver<A>,Set<A>> observers
          A set containing the current added observers and their associated aspects they subscribe to.
 
Fields inherited from class dk.rode.thesis.meta.model.AbstractSequence
state
 
Constructor Summary
protected SequenceObserversSequence()
          Sub-class no-arg constructor.
protected SequenceObserversSequence(AspectObservableSequence<SequenceObserver<A>,A,E> sequence)
          Copy constructor.
 
Method Summary
 boolean addObserver(SequenceObserver<A> observer)
          Adds the observer supplied as observer to this observable, if not already.
 boolean addObserver(SequenceObserver<A> observer, A aspect)
          Adds the observer supplied as observer to this observable for the aspect supplied as aspect, if not already.
protected abstract  E doNext()
          Hook for sub-classes to perform the actual next() operation without notifying observers.
protected abstract  A getAspect()
          Hook for sub-classes to deliver the changed aspect value to notify observers about immediately after doNext() has been invoked, if any.
 Set<A> getAspects(SequenceObserver<A> observer)
          Returns a read-only set of the aspects the observer supplied as observer subscribes to in this observable, if any.
 Collection<SequenceObserver<A>> getObservers()
          Returns the observers currently associated with this observable sequence.
 Collection<SequenceObserver<A>> getObservers(A aspect)
          Returns the observers subscribed to the aspect supplied as aspect in this observable.
 E next()
          Returns the next element from this sequence.
 boolean removeObserver(Object observer)
          Removes the observer supplied as observer from this observable, if already added.
 boolean removeObserver(Object observer, A aspect)
          Removes the observer supplied as observer from this observable with regards to the aspect supplied as aspect, if already added to it.
 void sequenceEvent(Sequence<?> sequence, A aspect)
          Notification method that is invoked when the sequence supplied as sequence has changed its state to state.
 
Methods inherited from class dk.rode.thesis.meta.model.AbstractSequence
getStringablePolicy, reset, state, toString, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface dk.rode.thesis.meta.model.Sequence
bounded, consistent, copy, current, reset, state, unique
 
Methods inherited from interface dk.rode.thesis.strategy.Stringable
getStringablePolicy, toString
 

Field Detail

observers

private final Map<SequenceObserver<A>,Set<A>> observers
A set containing the current added observers and their associated aspects they subscribe to.

If the associated set contains null, the observer subscribes to all aspect values.

Never null, but may be empty.

Constructor Detail

SequenceObserversSequence

protected SequenceObserversSequence()
Sub-class no-arg constructor.


SequenceObserversSequence

protected SequenceObserversSequence(AspectObservableSequence<SequenceObserver<A>,A,E> sequence)
Copy constructor.

Parameters:
sequence - The observable sequence to copy; cannot be null.
Throws:
NullPointerException - If sequence is null.
Method Detail

addObserver

public boolean addObserver(@Participant(value="ConcreteObserver")
                           SequenceObserver<A> observer)
Description copied from interface: Observable
Adds the observer supplied as observer to this observable, if not already.

Specified by:
addObserver in interface Observable<SequenceObserver<A>>
Parameters:
observer - The observer to add; cannot be null.
Returns:
True if observer was added, false if not.
See Also:
Observable.removeObserver(Object)

addObserver

public boolean addObserver(@Participant(value="ConcreteObserver")
                           SequenceObserver<A> observer,
                           A aspect)
Description copied from interface: AspectObservable
Adds the observer supplied as observer to this observable for the aspect supplied as aspect, if not already.

If aspect is null, observer will be subscribed to all possible aspect values.

Specified by:
addObserver in interface AspectObservable<SequenceObserver<A>,A>
Parameters:
observer - The observer to add; cannot be null.
aspect - The aspect to subscribe to; null means all.
Returns:
True if observer was added, false if not.
See Also:
AspectObservable.removeObserver(Object, Object)

doNext

protected abstract E doNext()
Hook for sub-classes to perform the actual next() operation without notifying observers.

Returns:
The next element; never null.

getAspect

protected abstract A getAspect()
Hook for sub-classes to deliver the changed aspect value to notify observers about immediately after doNext() has been invoked, if any.

If this method returns null, no notification is performed as the aspect has not changed.

Returns:
The changed aspect; or null if not changed.

getAspects

public Set<A> getAspects(SequenceObserver<A> observer)
Description copied from interface: AspectObservable
Returns a read-only set of the aspects the observer supplied as observer subscribes to in this observable, if any.

Specified by:
getAspects in interface AspectObservable<SequenceObserver<A>,A>
Parameters:
observer - The observer; cannot be null.
Returns:
A read-only list containing the aspect subscriptions; never null, but can be null.

getObservers

public Collection<SequenceObserver<A>> getObservers()
Description copied from interface: Observable
Returns the observers currently associated with this observable sequence.

No specific order is maintained.

Modifying the returned collection will not affect this observable.

Specified by:
getObservers in interface Observable<SequenceObserver<A>>
Returns:
The collection of observers; never null, but can be empty.

getObservers

public Collection<SequenceObserver<A>> getObservers(A aspect)
Description copied from interface: AspectObservable
Returns the observers subscribed to the aspect supplied as aspect in this observable.

Specified by:
getObservers in interface AspectObservable<SequenceObserver<A>,A>
Parameters:
aspect - The aspect; null means all.
Returns:
The observers subscribing to the aspect supplied as aspect; never null, but can be empty.

next

public final E next()
Returns the next element from this sequence.

Observers associated with this observable sequence are notified with the (new) aspect of this sequence if getAspect() returns a non-null value.

Specified by:
next in interface Sequence<E>
Returns:
The next element; never null.
See Also:
doNext(), getAspect(), sequenceEvent(Sequence, Object)

removeObserver

public boolean removeObserver(Object observer)
Description copied from interface: Observable
Removes the observer supplied as observer from this observable, if already added.

Trying to remove an observer that is not associated with this observable has no effect.

Specified by:
removeObserver in interface Observable<SequenceObserver<A>>
Parameters:
observer - The observer to remove; cannot be null.
Returns:
True if observer was removed, false if not.
See Also:
Observable.addObserver(Object)

removeObserver

public boolean removeObserver(Object observer,
                              A aspect)
Description copied from interface: AspectObservable
Removes the observer supplied as observer from this observable with regards to the aspect supplied as aspect, if already added to it.

Trying to remove an observer that is not associated with this observable or to an unsubscribed aspect has no effect.

Specified by:
removeObserver in interface AspectObservable<SequenceObserver<A>,A>
Parameters:
observer - The observer to remove for aspect; cannot be null.
aspect - The aspect in question; null means all.
Returns:
True if observer was removed from the subscription to aspect (or all if null), false if not.
See Also:
AspectObservable.addObserver(Object, Object)

sequenceEvent

public void sequenceEvent(Sequence<?> sequence,
                          A aspect)
Description copied from interface: SequenceObserver
Notification method that is invoked when the sequence supplied as sequence has changed its state to state.

The type of sequence is not defined; it cannot be assumed observable, or even of the type this observer was attached to; it might be adapted, decorated, composite, or proxied.

Specified by:
sequenceEvent in interface SequenceObserver<A>
Parameters:
sequence - This sequence; cannot be null.
aspect - The current (new) aspect; cannot be null.

Gunni Rode / rode.dk

Feel free to use and/or modify the Java 6 source code developed for this thesis AT YOUR OWN RISK, but note that the source code comes WITHOUT ANY — and I do mean WITHOUT ANY — form of warranty WHAT SO EVER!

The original thesis and source code are available at rode.dk/thesis.