Archive

Archive for February, 2010

Implementing the Observer pattern in JavaFX – Again

February 21, 2010 Leave a comment

I’ve just updated the previous article to use a much better solution for the Observer pattern. I’ve updated the source code too.

The final source is here

The solution I’m proposing is located in the script observer.Implementation.fx. See the previous article for its usage; which is much lighter than its predecessor !

Sorry for the mess…

Categories: Uncategorized

Implementing the Observer pattern in JavaFX

February 18, 2010 2 comments

I’ve seen from various sources people are wondering how to implement the Observer Design Pattern in JavaFX. I’m writing a small JavaFX game in my spare time and had to find the answer to that question too. I thought I might as an aftermath share the observations.

In the ideal world the pattern should be implemented as follows

  1. Intuitive usage with limited coding.
  2. Native to JavaFX; I don’t have to implement this pattern all over again each time I need this pattern.
  3. With multiple Observers (obviously).
  4. Unregistering on demand. (ie. avoid memory leaks)

Btw, there is an excellent Refcard about the classic design patterns.

Using closures

JavaFX comes with closures and function values. It basically means a function reference can be stored into a variable and shovelled around as arguments of other functions. In the end the variable can be invoked to call the function it references. No need to know where the function implementation resides any more and it’s ideal for function callbacks.

// declare a function to call
function hello( name:String ) :Void {
   println("Hello {name}");
}

// assign the closure to the 'myFunction' variable.
// note that the type declaration is not needed.
def myFunction: function(:String):Void = hello;

// invoking the function. Yields 'Hello it's me !' in the standard output
myFunction( "it's me !" );

To implement the Observer pattern on a basic level you might proceed as follows

/**
 * The Subject class; registering observers and notifying them at due time
 */
public class Subject {
  public var onUpdate:function(:String):Void;

  public function notifies() :Void {
   // note that JavaFX would forgive your
   // NPE when no Observer is known !
    onUpdate("Wake up !");
  }
}

/**
 * The Observer class; being notified by the Subject when needed.
 */
public class Observer {
  public function update( title:String ) :Void {
    println( title );
  }
}

public function run() :Void {
 // create the Observer
 def observer = Observer{};

 // create the Subject and register the Observer
 def subject  = Subject {
   onUpdate: observer.update;
 };

 // have the Subject notify the Observers
 subject.notifies();
}
Observations
  • Rule (1) is met : The usage is fairly simple.
  • Rule (2) is met : JavaFX does the work of event notification and registering.
  • Rule (3) is not met : Only one Observer is allowed.
  • Rule (4) is met : Unsubscribe by setting the variable OnUpdate variable to null.
However …
  • Re-assigning the onUpdate variable overwrites the reference to the previous Observer !
  • The previous statement implies also you can’t rely on the fact that your Observer will always be called.
  • Making the onUpdate variable public-init prevents overwriting. But it would also prevent unregistering !
  • External code can invoke the Observer as onUpdate it is a public variable.
Use this method when
  • Just one Observer will do.
  • As a simple function callback implementation.
  • Preferably don’t need to unsubscribe so you can use public-init.

Using Closures with Triggers

JavaFX has the ability to execute custom code when the value of a variable has been changed. Adding a trigger to the onUpdate variable would allow me to register multiple Observer objects.

/**
 * The Subject class; registering observers and notifying them at due time
 */
public class Subject {
 // List of Observers
 // Note that function(:String):Void[] is not a valid syntax !
 var updates:function(:String)[];

 public var onUpdate:function(:String):Void on replace {
   if ( onUpdate != null ) {
     insert onUpdate into updates;
     onUpdate = null;
   }
 };

 public function notifies() :Void {
   for ( update in updates ) {
     update("Wake up !");
   }
 }
}

/**
 * The Observer class; being notified by the Subject when needed.
 */
public class Observer {
  public function update( title:String ) :Void {
    println( "Subject says {title}" );
  }
}

public function run() :Void {
 // create the Observers
 def observer1 = Observer{};
 def observer2 = Observer{};

 // create the Subject and register the Observer
 def subject  = Subject {
   onUpdate: observer1.update;
 };

 // the second Observer registers
 subject.onUpdate = observer2.update;

 // have the Subject notify the Observers
 subject.notifies();
}

Adding the on replace compound statement (line 9) to the onUpdate adds the closure to a sequence of closures (line 7). After that the variable is set to null to avoid external access to the Observer. The test on the value (line 10) is needed to avoid an endless loop. Setting the onUpdate variable to null (line 12) re-invokes the trigger !

The Subject now cycles through the updates sequence to notify its Observers with a simple loop.

Observations
  • Rule (1) is met : The usage is fairly simple.
  • Rule (2) is met : JavaFX does the event handling. Although the registration is implemented explicitly.
  • Rule (3) is met : Multiple Observers can be used.
  • Rule (4) is not met : Observers can not be unregistered. The assignment works one-way.
However …
  • The code must be repeated for each observable property: a sequence with observers, a variable with trigger and a function with loop to call the observers. This would quickly escalate in a lot of boilerplate. To my knowledge there is no way to implement this is a separate entity of some sort. Please drop me a mail if you would happen to know how.
  • It’s an open door to memory leaks. Unused Observers will still be referenced by the subject.
  • Weak references java.lang.ref.WeakRefence is no solution either. Even when releasing the Observer
Use this method when
  • The number of events and Subjects is limited. The coding has to be repeated for every describable event.
  • You don’t need to unregister the Observers.

Hacky, but still cool though… 🙂

Binding + trigger with Subject variables

Another neat feature of JavaFX is the possibility to bind a variable to a variable of another class. When the original variable changes, the change is reflected to the binding variable. The trick here is to add a trigger to this binding variable so that changes can be intercepted.

class Subject {
 // The observer listens to changes of this var
  public var blabla = "bla";
}

class Observer {
  // we need a reference to the subject in order to be
  // able to bind with it
  public var subject:Subject;

  // every change in this variable will be intercepted
  // as a result it is 'listening' to changes of the Subject
  var blabla = bind subject.blabla on replace {
                 update( blabla );
               }

  function update( feedback:String ) :Void {
    println("Subject says: {feedback}");
  }
}

Using the code would look like this

def subject  = BindingSubject{};
// register the observer to its subject
def observer = Observer{
                 subject: subject
               };

// let's make changes the observer will intercept
subject.blabla = "blo";
subject.blabla = "bli";
Observations
  • Rule (1) is met : The usage is simple.
  • Rule (2) is met : JavaFX does the event handling and registration.
  • Rule (3) is met : I can have any number of Observers listening to the Subject.
  • Rule (4) is not met : Unregistering is not possible. Setting the blabla variable of the Observer to null is not allowed as it is a bound variable.
However …
  • This trick only works with the Subject’s public (not public-read !) variables and variables of Subjects in the same script file.
  • It is limited to event handling where all data needed from the Subject is publicly available.
  • It is not unlikely that the Subject is in a mutating state when the variable change is intercepted by the Observer. Meaning that other variables of the Subject might be outdated !
  • Because it was never the intention of the Subject to implement the pattern with variables in the first place, it’s not unlikely that a new version of the Subject causes the mutating issue to occur while it didn’t with the earlier version.
Use this method when
  • Don’t. Simply because it violates an essential rule of our trade: Use things the way they are meant to be used.

Mixin event dispatcher

In a not so distant past I was working on a Java/Flex project. And although Flex is not exactly my favourite language, I have to admit it does a good job in event handling/subscription. The same functionality can be achieved with JavaFX. It would even be better because JavaFX supports multiple-inheritance with mixin classes. In Flex you’re forced to have EventDispatcher as superclass.

/**
 * A mixin class used to enable event listening and
 * dispatching for any class.
 */
public mixin class EventDispatcher {

 var entries: EventTypeEntry[];

 def context      = FXLocal.getContext();
 def mirrorOfThis = context.mirrorOf( this );
 def typeOfThis   = mirrorOfThis.getType();

 /**
 * Find the event types declared by the implementing class.
 * The naming convention is that the name should start with
 * 'EVENT_TYPE_' AND it should be a String.
 */
 postinit {
   for ( variable in typeOfThis.getVariables( true ) ) {
     if ( variable.getName().startsWith("EVENT_TYPE_") and "java.lang.String".equals( variable.getType().getName() ) ) {
       def value = variable.getValue( mirrorOfThis ).getValueString();
       delete value from eventTypes; // delete first to remove duplicates
       insert value into eventTypes;
     }
   }
 }

 /**
  * Add an observer to the event dispatcher.
  */
 public function addEventListener( type:String, callbackFunction:Object ) :Void {
 // the event type must be known by the dispatcher
   if ( sizeof eventTypes[ x | x == type ] == 0 ) {
     throw new RuntimeException( "Unknown event type '{type}'" );
   }

 // is the callback function argument a function ?
   if ( not isFunction( callbackFunction ) ) {
     throw new RuntimeException("The passed callback is not a function !")
   }

 // Add the listener to the event type
   def entry = entries[ x | x.type == type ];
   if ( sizeof entry == 0 ) {
     insert EventTypeEntry {
       type: type;
       listeners: callbackFunction;
     } into entries;
   }
   else {
     insert callbackFunction into entry[0].listeners;
   }
 };

 /**
 * Check whether the passed object is a valid callback function.
 * TODO Find a generic way to check this.
 */
function isFunction( callback:Object ) :Boolean {
   // is it a function with one Object argument ?
   try {
     def test = (callback as function(:Object):Void);
     return true;
   } catch ( Exception:Exception ) {}

   // is it a function with two Object arguments ?
   try {
     def test = (callback as function(:Object,:Object):Void);
     return true;
   } catch ( Exception:Exception ) {}

   // repeat the block of code for each additional argument. Etc...

   // it's not a function. Or it is, but it has more arguments than expected.
   return false;
 }

 public function removeEventListener( type:String, callbackFunction:Object ) :Void {
   def entry = entries[ x | x.type == type ];
   if ( sizeof entry > 0 ) {
     delete callbackFunction from entry[0].listeners;
   }
 }

/**
 * The dispatch function is repeated for an ever longer list of arguments.
 * This way the calling code is clean.
 * Writing one function accepting a sequence of Objects would work too but
 * then the calling function should explicitly declare a sequence.
 */
 public function dispatch( type:String, arg0:Object ) {
   def entry = entries[ x | x.type == type ];
   if ( sizeof entry > 0 ) {
     for ( listener in entry[0].listeners ) {
       (listener as function( :Object ))( arg0 );
     }
   }
 }

 public function dispatch( type:String, arg0:Object, arg1:Object ) {
   def entry = entries[ x | x.type == type ];
   if ( sizeof entry > 0 ) {
     for ( listener in entry[0].listeners ) {
       (listener as function( :Object, :Object ))( arg0, arg1 );
     }
   }
 }

 // Etc...
}

/**
 * Represents a list of Observers for one specific event type
 */
class EventTypeEntry {
 public-init var type:String;
 public var listeners: Object[];
}

An example of the usage of this class

/**
 * Declare the Subject. Declare the EVENT_TYPE_
 * variables so they can be picked up by the
 * mixin class.
 */
public class Subject extends EventDispatcher {
  public def EVENT_TYPE_WAKEUP = "wakeup";
  public def EVENT_TYPE_SLEEP  = "sleep";
}

/**
 * Declare the Observer with its callback functions
 */
public class Observer {
  public function wakeUp( title:String ) :Void {
    println("wakeUp: {title}");
  }
  public function sleep( title:String ) :Void {
    println("sleep: {title}");
  }
}

/**
 * And the small demo showing it works. Not.
 */
public function run() :Void {
 def subject   = Subject{};
 def observer1 = Observer {};
 def observer2 = Observer {};

 // demo 1 : add event listeners and call them
 subject.addEventListener( subject.EVENT_TYPE_WAKEUP, observer1.wakeUp );
 subject.addEventListener( subject.EVENT_TYPE_WAKEUP, observer2.wakeUp );
 subject.addEventListener( subject.EVENT_TYPE_SLEEP, observer1.sleep );
 subject.addEventListener( subject.EVENT_TYPE_SLEEP, observer2.sleep );
 subject.dispatch( subject.EVENT_TYPE_SLEEP , "Sleep right now !");
 subject.dispatch( subject.EVENT_TYPE_WAKEUP, "Stop sleeping !");

 // demo 2 : remove some listeners and do the same call.
 subject.removeEventListener( subject.EVENT_TYPE_WAKEUP, observer2.wakeUp );
 subject.removeEventListener( subject.EVENT_TYPE_SLEEP, observer1.sleep );
 subject.dispatch( subject.EVENT_TYPE_SLEEP , "Sleep right now !");
 subject.dispatch( subject.EVENT_TYPE_WAKEUP, "Stop sleeping !");
 // euh... why are all four listeners still responding ?
}

Creating a Subject

A class becomes a Subject as soon as it extends the EventDispatcher mixin class. Because it is a mixin, any class can extend it. It won’t impose any constraint on the implementing class’ inheritance. For convenience I added the rule that the event types are declared as String variables whose name starts with EVENT_TYPE_. They are retrieved by introspection by the EventDispatcher class. It’s easy to implement and it allows a direct reference when (un)subscribing.

public class Subject extends EventDispatcher {
  public def EVENT_TYPE_WAKEUP = "wakeup";
  public def EVENT_TYPE_SLEEP  = "sleep";
}

The example declares a Subject with two event types: EVENT_TYPE_WAKEUP and EVENT_TYPE_SLEEP. That’s all there is to it.

Registering an Observer

An observer is registered in one statement: a call to the addEventListener function.

public class Observer {
  public function wakeUp( title:String ) :Void {
    println("wakeUp: {title}");
  }
  public function sleep( title:String ) :Void {
    println("sleep: {title}");
  }
}

def subject = Subject{};
def observer = Observer {};
subject.addEventListener( subject.EVENT_TYPE_WAKEUP, observer.wakeUp );

Again, few code is needed to perform this task.

Notifying the Observers

The Subject can notify its Observers by a single instruction

subject.dispatch( EVENT_TYPE_WAKEUP, "Time for breakfast !" );

The dispatch function has been duplicated to allow notification with two, three, four, etc… number of arguments. (Alas, JavaFX doesn’t support functions with a variable number of arguments.) These arguments will be passed to the registered functions of the particular event type. It’s not exactly clean and generic, but it keeps the dispatch instruction simple and all the messy code into a single class.

Unregistering an Observer

An Observer can unregister from a Subject with the instruction

observer.removeEventListener( EVENT_TYPE_WAKEUP, observer.wakeUp );

And I should have said “That’s all there is to it !”. Alas alas, until yesterday I didn’t know that each usage of observer.wakeUp would yield a different object ! As a result the listeners sequence (line 7 in EventDispatcher) refuses to remove the passed function value. Simply because the it is different from the one passed when registering.

Maybe this is by design. Which is not impossible if they’re trying to implement closures; a bunch of code with a fixed/closed state. But I hope this is a bug because otherwise event handling will be fairly limited in JavaFX. For example it won’t even be possible to check whether the Observer is already subscribed; to avoid duplicate dispatching. I started a thread in the JavaFX fora to find an explanation (and a solution !) to this problem. I invite anyone interested to share his/her views.

Observations
  • Rule (1) is met insofar the usage is fairly simple.
  • Rule (2) is not met : A lot of additional coding is needed. Luckily it is limited to a single class : EventDispatcher.
  • Rule (3) is met : Multiple Observers can subscribe.
  • Rule (4) should have been met : See the red text above why it doesn’t.
However …
  • Although this solution looks more robust than the previous one, it’s not better. We have more coding but still can’t unsubscribe Observers.
Use this method when
  • You have a lot of Subjects and event types.
  • You don’t need to unsubscribe Observers.
  • My initial intention was to declare this method the best of those I tried. Unfortunately the unregistration issue breaks it.

Using the classic way: Events

Everybody who is familiar with Swing has done it : Writing property change event handlers with PropertyChangeSupport and have your listeners implement PropertyChangeListener. This can be done in JavaFX too. But it would be a shame because it doesn’t leverage closures at all. The problem of the previous method is solved if instead of passing closures (function values) for subscription you would pass the Observer itself.

Out of my previous attempts I distilled a working solution with no too much boilerplate and meeting our requirements set at the beginning of this article and supports weak referenced Observers. I’m including the source code at the bottom of the article. The solution is a mix of the previous ones, but alas, without using these cool closures.

An example of the usage of the thing I brewed. (I’m sparing you from the source code of the previous version of the article)

First of all, let’s create a Subject class. It should extend the EventDispatcher class and insert its event types into the sequence eventTypes. If you would simply replace the eventTypes sequence you might erase the event types defined by a superclass (ie SubSubject). Also note that the event types are not defined as variables of the Subject class, but rather as script-level variables. This is because otherwise you’ll create a direct dependency of the Observer with the Subject when subscribing to events (see later).

The EventDispatcher class is a mixin class. This means literally any exting class can become a Subject in the Observer pattern.

/////////////////////////////////////////////////////////////////////////////////
// VERY IMPORTANT !!!!! Put these ON TOP of the source code !!!!
//                      Otherwise these variables won't be initialized on time !
/////////////////////////////////////////////////////////////////////////////////
public def EVENT_TYPE_WAKEUP:String = "wakeup";
public def EVENT_TYPE_SLEEP:String  = "sleep";

class Subject extends EventDispatcher {
    init {
        insert [ EVENT_TYPE_WAKEUP, EVENT_TYPE_SLEEP ] into eventTypes;
    }
}

After that, let’s create an Observer class.

class Observer extends EventListener {
    override public function handleEvent (event : Event): Void {
    // write your event handling code here ...
    }
}

The Observer class has to extends the EventListener mixin class. This class contains an abstract function handleEvent which must be implemented by the Observer class. This function will be called when the subject wants to notify its Observers. It will pas an object of type Event. This object encapsulates all data describing the notification. The EventListener class is a mixin class. Again allowing any existing class to play the Observer role in this patterns; simply by extending the EventListener class.

Finally, let’s create an Event class.

class WakeupEvent extends Event {
    override def type = EVENT_TYPE_WAKEUP;
};

The Event concept is not part of the Observer pattern. It’s a class encapsulating the notification the Subject is passing to its Observers. In this case the Event class is a mixin class every class should extend to allow it to become a notification. The subclass should override the type variable to assign it a unique value. This value is used when (un)subscribing Observers.

And again this is a mixin class; any exisiting class can play the role of Event in this pattern. Also your already existing domain model classes !!!

Once all the declarations are done we can start using it. A simple example :

// create the Subject
  def subject = Subject{};
// create the Observer
  def observer = Observer{};
// have to Observer subscribe to wake up event
  subject.addEventListener( EVENT_TYPE_WAKEUP, observer );
// have the Subject notify its Observers with a blank wake up event
  subject.dispatch( WakeupEvent{} );
// have the Observer unsubscribe to the wake up event
  subject.removeEventListener( EVENT_TYPE_WAKEUP, observer);

The same example with weak referencing (spot the difference !)

// create the Subject
  def subject = Subject { weakReferenced: true };
// create the Observer
  def observer = Observer{};
// have to Observer subscribe to wake up event
  subject.addEventListener( EVENT_TYPE_WAKEUP, observer );
// have the Subject notify its Observers with a blank wake up event
  subject.dispatch( WakeupEvent{} );
// have the Observer unsubscribe to the wake up event
  subject.removeEventListener( EVENT_TYPE_WAKEUP, observer);

Weak-references are used to have the garbage collector erase objects which only remaining references are weak. And not hard as it is by default. So, theoretically in the last example it means an Observer should not even need to unsubscribe. The garbage collector will do that for you. This is very valuable in cases it’s difficult to keep a reference to the Observer. The drawback however is that the Observer is only removed during garbage collection. Meaning that even if the only remaining reference to the Observer is weak, the Observer still gets notified for as long as the garbage collector hasn’t run.

Observations
  • Rule (1) is met : The usage is fairly simple.
  • Rule (2) is met : The implementation is quite simple as well.
  • Rule (3) is met : Multiple observers are allowed.
  • Rule (4) is met : Observers can unsubscribe. And when weak-referenced, also automatically at the next garbage collector run.
  • Your existing classes can immediately participate because Subject, Observer and Event are all mixin classes.
However
  • The solution is not using any closure feature at all. Which is really sad because closures are supposed to be one of JavaFX’s strong points.
Use this method when
  • Unsubscription of Observers is needed.
  • The other methods are not applicable in your case.
  • You’re new to JavaFX and have to implement robust event handling right now.

Conclusions

  • There are various ways of implementing the Observer pattern at some level.
  • For simple callback functions I would advise the very first solution Using Closures. It’s also the way it is done in the JavaFX API anyway.
  • For something else I won’t advise to use closures just yet because of the comparison issue. It saddens me to say it but I would advise to go for the non-closure way. Because it’s the only solution I have found to be robust, clear and stable. All the other solutions present drawbacks which might cause you to run in serious trouble at some time.

I’m not exactly the JavaFX expert. So I really hope somebody reads this and comes forward to tell me I’m all wrong about the closures not being ready yet for this kind of usage. Please, prove me wrong ! 🙂

Anyway, I hope this article helped at least some people with their work. The source code of the examples is provided as a Netbeans project. Click on the floppy disk to download it.

important: The code as described in the last solution is located in observer.Implementation.fx. The other classes are the other examples of this article and test code to prove the final implementation does really work.

Jan Goyvaerts @ JFXWorks

Source code

/**
* A mixin class every observer/listener should implement
* in order to get events.
*/
public mixin class EventListener {
public abstract function handleEvent( event:Event ):Void;

public function getListener() :EventListener {
return this;
}
}

class WeakReferencedEventListener extends EventListener {
var referent:EventListener;
var reference:WeakReference;

postinit {
if ( referent == null ) {
throw new IllegalStateException(“A referent event listener should have been set.”);
}
// put the referent into a weak reference
reference = new WeakReference( referent );
// cut the hard reference
referent  = null;
}

override public function handleEvent (event : Event) :Void {
def referent = reference.get();
// is it still referencing something ?
if ( referent != null ) {
(referent as EventListener).handleEvent(event);
}
}

override public function getListener() :EventListener {
return reference.get() as EventListener;
}
}

/**
* Event class to allow the generic usage of events.
* Override the ‘type’ variable to assign a new value.
*
* Class TestEvent extends Event {
*   override def type = “test”;
* }
*
* It is created as a mixin class to allow any object
* to become an event class. Even one of your domain classes.
*/
public mixin class Event {
var typeSet = false;
// make the type variable immutable. It can not be made protected
// because subclasses might reset it. It can not be made public-init
// because everyone can override the value. It can’t be a def
// because you can’t override it.
public var type:String on replace {
if ( typeSet ) {
throw new IllegalStateException(“Can not reset the type value. Override the ‘type’ variable instead.”);
}
typeSet = true;
};
}

/**
* Mixin class to be implemented by each class dispatching events.
*
* The implementing class has to declare the event types it will handle
* simply by declaring public String variables named EVENT_TYPE_.
*
* In theory this class could be final as it contains all needed code
* to register, unregister and dispatch events.
*/
public mixin class EventDispatcher {

// event types the dispatcher can handle
protected var eventTypes: String[];

// a map-like structure to store the listeners per event type.
var listeners:EventListenerEntry[];

// indicates whether the listeners should be weak-referenced
public-init var weakReferenced = false;

// stuff needed to find the event types by introspection
def context      = FXLocal.getContext();
def mirrorOfThis = context.mirrorOf( this );
def typeOfThis   = mirrorOfThis.getType();

/**
* Find the event types declared by the implementing class.
* The naming convention is that the name should start with ‘EVENT_TYPE_’ AND it should be a String
*/
postinit {
for ( variable in typeOfThis.getVariables( true ) ) {
if ( variable.getName().startsWith(“EVENT_TYPE_”) and “java.lang.String”.equals( variable.getType().getName() ) ) {
def value = variable.getValue( mirrorOfThis ).getValueString();
insert value into eventTypes;
}
}
// check for duplicates – they might mean identical values for different event types
var lastType = “zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz”;
for ( type in Sequences.sort( eventTypes ) ) {
if ( type == lastType ) {
throw new IllegalStateException(“Duplicate event type naming ! name= {type}”);
}
lastType = type as String;
}
}

// Add an observer to the list of observers
public function addEventListener( type:String, listener:EventListener ) :Void {
// check arguments
if ( type == null or type.trim().equals(“”) or listener == null ) {
throw new IllegalArgumentException(“Invalid arguments: type= {type} listener= {listener}”);
}

// get the type
def types = eventTypes[ x | x.equals(type) ];
if ( sizeof types == 0 ) {
throw new IllegalArgumentException(“Type {type} is not a subscribable type for this object.”);
}

// make the registration
def entry = listeners[ x | x.type == type ];

// this should NOT happen !
if ( sizeof entry > 1 ) {
throw new IllegalStateException(“More than one entry for event type {type} !”);
}
// a new entry
else if ( sizeof entry == 0 ) {
insert EventListenerEntry {
type: type
listeners: adaptListener( listener )
} into listeners;
}
// an existing entry
else {
insert adaptListener(listener) into entry[0].listeners;
}

// cleanup invalid listeners
cleanupListeners();
}

function adaptListener( listener:EventListener ) :EventListener {
if ( weakReferenced ) {
WeakReferencedEventListener {
referent: listener
}
}
else {
listener;
}
}

// Remove the given observer from the list of known observers
public function removeEventListener( type:String, listener:EventListener ) :Void {
// make the unrgistration
def entry = listeners[ x | x.type == type ];

// this should NOT happen !
if ( sizeof entry > 1 ) {
throw new IllegalStateException(“More than one entry for event type {type} !”);
}
else if ( sizeof entry == 1 ) {
def toDelete = entry[0].listeners[ x | x.getListener() == listener ];
for ( del in toDelete ) {
delete del from entry[0].listeners;
}
}

// cleanup invalid listeners
cleanupListeners();
}

// Dispatch the event to the known observers
public function dispatch( event:Event ) :Void {
// check arguments
if ( event == null or event.type == null or event.type.trim().equals(“”) ) {
throw new IllegalArgumentException(“Invalid arguments: event= {event} type= {event.type}”);
}

// check the type
def types = eventTypes[ x | x.equals(event.type) ];
if ( sizeof types == 0 ) {
throw new IllegalArgumentException(“Type {event.type} is not a subscribable type for this object.”);
}

// dispatch
def type  = types[0];
def entry = listeners[ x | x.type == type ];
if ( sizeof entry == 1 ) {
for ( listener in entry[0].listeners ) {
listener.handleEvent( event );
}
}

// cleanup invalid listeners
cleanupListeners();
}

/**
* This code is really meant for weak references being freed
*/
function cleanupListeners() :Void {
for ( entry in listeners, listener in entry.listeners[ x | x.getListener() == null ]  ) {
delete listener from entry.listeners;
}
}
}

/**
* One entry in map-like structure of listeners/event type
*/
class EventListenerEntry {
public-init var type:String;
public var listeners:EventListener[];
}