<|start_filename|>lib/src/core/Controller.dart<|end_filename|>
part of puremvc;

/**
 * A PureMVC MultiCore [IController] implementation.
 *
 * In PureMVC, an [IController] implementor
 * follows the 'Command and Controller' strategy, and
 * assumes these responsibilities:
 *
 * -  Remembering which [ICommand]s are intended to handle which [INotification]s.
 * -  Registering itself as an [IObserver] with the [View] for each [INotification] that it has an [ICommand] mapping for.
 * -  Creating a new instance of the proper [ICommand] to handle a given [INotification] when notified by the [IView].
 * -  Calling the [ICommand]'s [execute] method, passing in the [INotification].
 *
 * See [INotification], [ICommand]
 */
class Controller implements IController
{

  /**
   * Constructor.
   *
   * This [IController] implementation is a Multiton, so you should not call the constructor directly,
   * but instead call the static [getInstance] method.
   *
   * -  Throws [MultitonErrorControllerExists] if instance for this Multiton key has already been constructed
   */
  Controller( String key )
  {
    if ( instanceMap[ key ] != null ) throw new MultitonErrorControllerExists();
    multitonKey = key;
    instanceMap[ multitonKey ] = this;
    commandMap = new Map<String,Function>();
    initializeController();
  }

  /**
   * Initialize the [IController] Multiton instance.
   *
   * Called automatically by the constructor.
   *
   * Note that if you are using a custom [IView] implementor in your application,
   * you should also subclass [Controller] and override the [initializeController] method,
   * setting [view] equal to the return value of a call to [getInstance] on your [IView] implementor.
   */
  void initializeController( )
  {
    view = View.getInstance( multitonKey );
  }

  /**
   * [IController] Multiton Factory method.
   *
   * -  Returns the [IController] Multiton instance for the specified key
   */
  static IController getInstance( String key )
  {
    if ( key == null || key == "" ) return null;
    if ( instanceMap == null ) instanceMap = new Map<String,IController>();
    if ( instanceMap[ key ] == null ) instanceMap[ key ] = new Controller( key );
    return instanceMap[ key ];
  }

  /**
   * Execute the [ICommand] previously registered as the
   * handler for [INotification]s with the given notification's name.
   *
   * -  Param [note] - the [INotification] to execute the associated [ICommand] for
   */
  void executeCommand( INotification note )
  {
    Function commandFactory = commandMap[ note.getName() ];
    if ( commandFactory == null ) return;

    ICommand commandInstance = commandFactory();
    commandInstance.initializeNotifier( multitonKey );
    commandInstance.execute( note );
  }

  /**
   * Register an [INotification] to [ICommand] mapping with the [Controller].
   *
   * -  Param [noteName] - the name of the [INotification] to associate the [ICommand] with.
   * -  Param [commandFactory] - a function that creates a new instance of the [ICommand].
   */
  void registerCommand( String noteName, Function commandFactory )
  {
    if ( commandMap[ noteName ] == null ) {
      view.registerObserver( noteName, new Observer( executeCommand, this ) );
    }
    commandMap[ noteName ] = commandFactory;
  }

  /**
   * Check if an [ICommand] is registered for a given [INotification] name with the [IController].
   *
   * -  Param [noteName] - the name of the [INotification].
   * -  Returns [bool] - whether an [ICommand] is currently registered for the given [noteName].
   */
  bool hasCommand( String noteName )
  {
    return commandMap[ noteName ] != null;
  }

  /**
   * Remove a previously registered [INotification] to [ICommand] mapping from the [IController].
   *
   * -  Param [noteName] - the name of the [INotification] to remove the [ICommand] mapping for.
   */
  void removeCommand( String noteName )
  {
    // if the Command is registered...
    if ( hasCommand( noteName ) )
    {
      // remove the observer
      view.removeObserver( noteName, this );

      // remove the command
      commandMap[ noteName ] = null;
    }
  }

  /**
   * Remove an [IController] instance.
   *
   * -  Param [key] multitonKey of the [IController] instance to remove
   */
  static void removeController( String key )
  {
    instanceMap[ key ] = null;
  }

  // Local reference to this core's IView
  IView view;

  // Mapping of Notification names to Command Class references
  Map<String,Function> commandMap;

  // The Multiton Key for this Core
  String multitonKey;

  // Multiton instance map
  static Map<String,IController> instanceMap;

}

class MultitonErrorControllerExists {
  const MultitonErrorControllerExists();

  String toString() {
    return "IController Multiton instance already constructed for this key.";
  }
}


<|start_filename|>lib/src/interfaces/IFacade.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC MultiCore Facade.
 *
 * The Facade Pattern suggests providing a single
 * class to act as a central point of communication
 * for a subsystem.
 *
 * In PureMVC, the [IFacade] acts as an interface between
 * the core MVC actors [IModel], [IView], [IController], and
 * the rest of your application, which (aside from view components
 * and data objects) is mostly expressed with [ICommand]s,
 * [IMediator]s, and [IProxy]s.
 *
 * This means you don't need to communicate with the [IModel],
 * [IView], [IController] instances directly, you can just go through
 * the [IFacade]. And conveniently, [ICommand]s, [IMediator]s, and
 * [IProxy]s all have a built-in reference to their [IFacade] after
 * initialization, so they're all plugged in and ready to communicate
 * with each other.
 *
 * See [IModel], [IView], [IController], [IProxy], [IMediator], [ICommand], [INotification]
 */
abstract class IFacade extends INotifier
{

	/**
     * Register an [IProxy] instance with the [IModel].
     *
     * -  Param [proxy] - an object reference to be held by the [IModel].
	 */
	void registerProxy( IProxy proxy );

    /**
     * Retrieve an [IProxy] instance from the [IModel].
     *
     * -  Param [proxyName] - the name of the [IProxy] instance to retrieve.
     * -  Returns the [IProxy] instance previously registered with the given [proxyName].
     */
    IProxy retrieveProxy( String proxyName );

    /**
     * Remove an [IProxy] instance from the [IModel].
     *
     * -  Param [proxyName] - name of the [IProxy] instance to be removed.
     * -  Returns [IProxy] - the [IProxy] that was removed from the [IModel].
     */
    IProxy removeProxy( String proxyName );

    /**
     * Check if an [IProxy] is registered with the [IModel].
     *
     * -  Param [proxyName] - the name of the [IProxy] instance you're looking for.
     * -  Returns [bool] - whether an [IProxy] is currently registered with the given [proxyName].
     */
    bool hasProxy( String proxyName );

    /**
     * Register an [INotification] to [ICommand] mapping with the [IController].
     *
     * -  Param [noteName] - the name of the [INotification] to associate the [ICommand] with.
     * -  Param [commandFactory] - a function that creates a new instance of the [ICommand].
     */
    void registerCommand( String noteName, Function commandFactory );

    /**
     * Remove a previously registered [INotification] to [ICommand] mapping from the [IController].
     *
     * -  Param [noteName] - the name of the [INotification] to remove the [ICommand] mapping for.
     */
    void removeCommand( String noteName );

    /**
     * Check if an [ICommand] is registered for a given [INotification] name with the [IController].
     *
     * -  Param [noteName] - the name of the [INotification].
     * -  Returns [bool] - whether an [ICommand] is currently registered for the given [noteName].
     */
    bool hasCommand( String noteName );

    /**
     * Register an [IMediator] instance with the [IView].
     *
     * Registers the [IMediator] so that it can be retrieved by name,
     * and interrogates the [IMediator] for its [INotification] interests.
     *
     * If the [IMediator] returns a list of [INotification]
     * names to be notified about, an [Observer] is created encapsulating
     * the [IMediator] instance's [handleNotification] method
     * and registering it as an [IObserver] for all [INotification]s the
     * [IMediator] is interested in.
     *
     * -  Param [mediator] - a reference to the [IMediator] instance.
     */
    void registerMediator( IMediator mediator );

    /**
     * Retrieve an [IMediator] from the [IView].
     *
     * -  Param [mediatorName] - the name of the [IMediator] instance to retrieve.
     * -  Returns [IMediator] - the [IMediator] instance previously registered in this core with the given [mediatorName].
     */
    IMediator retrieveMediator( String mediatorName );

    /**
     * Remove an [IMediator] from the [IView].
     *
     * -  Param [mediatorName] - name of the [IMediator] instance to be removed.
     * -  Returns [IMediator] - the [IMediator] that was removed from this core's [IView].
     */
    IMediator removeMediator( String mediatorName );

    /**
     * Check if an [IMediator] is registered with the [IView].
     *
     * -  Param [mediatorName] - the name of the [IMediator] you're looking for.
     * -  Returns [bool] - whether an [IMediator] is registered in this core with the given [mediatorName].
     */
    bool hasMediator( String mediatorName );

    /**
     * Register an [IObserver] to be notified of [INotification]s with a given name.
     *
     * -  Param [noteName] - the name of the [INotification] to notify this [IObserver] of.
     * -  Param [observer] - the [IObserver] to register.
     */
    void registerObserver( String noteName, IObserver observer );

    /**
     * Remove an [IObserver] from the list for a given [INotification] name.
     *
     * -  Param [noteName] - which [IObserver] list to remove from.
     * -  Param [notifyContext] - remove [IObserver]s with this object as the [notifyContext].
     */
    void removeObserver( String noteName, Object notifyContext );

    /**
     * Notify [IObserver]s.
     *
     * This method allows you to send custom [INotification] classes using the [IFacade].
     *
     * Usually you should just call [sendNotification] and pass the parameters,
     * never having to construct an [INotification] yourself.
     *
     * -  Param [note] the [INotification] to have the [View] notify [Observers] of.
     */
    void notifyObservers( INotification notification );

    /**
     * This [IFacade]'s Multiton key
     */
    void set multitonKey( String key );
    String get multitonKey;

    /**
     * This [IFacade]'s [IModel]
     */
    void set model( IModel modelInstance );
    IModel get model;

    /**
     * This [IFacade]'s [IView]
     */
    void set view( IView viewInstance );
    IView get view;

    /**
     * This [IFacade]'s [IController]
     */
    void set controller( IController controllerInstance );
    IController get controller;

}


<|start_filename|>test/Test_Notification.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_Notification
{
  _tests()
  {
    group('Notification', ()
    {
      test('Constructor minimum args', () {
        // Create a Notification with a name only
        String name   = "Test";
        mvc.INotification note = new mvc.Notification( name );

        // Make sure the note was created
        expect( note, isNotNull );
      });

      test('.name, getName()', () {
        // Create a Notification with name only
        String name   = "Test";
        mvc.INotification note = new mvc.Notification( name );

        // Make sure the name was set
        expect( name, equals( note.getName() ) );
        expect( name, equals( note.name ) );
      });

      test('.type, getType()', () {
        // Create a Notification with name and type only
        String name   = "Test";
        String type   = "Type";
        mvc.INotification note = new mvc.Notification( name, null, type );

        // Make Sure the type was set
        expect( type, equals( note.getType() ) );
        expect( type, equals( note.type ) );
      });

      test('.body, getBody()', () {
        // Create a Notification with a body
        String name   = "Test";
        List<String> body  = new List<String>();
        mvc.INotification note = new mvc.Notification( name, body );

        // Make sure the body was set
        expect( body, equals( note.getBody() ) );
        expect( body, equals( note.body ) );
      });
    });
  }

  run() {
    _tests();
  }
}

<|start_filename|>test/Test_View.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_View
{
  _tests()
  {
    group('ViewTest', ()
    {
      test('getInstance()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest1";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Make sure a View instance was returned
        expect( view, isNotNull );

        // Call getInstance() again
        mvc.IView again = mvc.View.getInstance( multitonKey );

        // Make sure the same View instance was returned
        expect( view, same(again) );
      });

      test('registerMediator(), hasMediator()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest2";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Register a Mediator
        String mediatorName = "ViewTest3Mediator";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );
        view.registerMediator( mediator );

        // Make sure it's registered
        expect( view.hasMediator( mediatorName ), isTrue );
      });

      test('retrieveMediator()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest3";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Register a Mediator
        String mediatorName = "ViewTest3Mediator";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );
        view.registerMediator( mediator );

        // Make sure same mediator is retrieved
        expect( view.retrieveMediator( mediatorName ), same(mediator) );
      });

      test('removeMediator()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest4";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Register a Mediator
        String mediatorName = "ViewTest4Mediator";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );
        view.registerMediator( mediator );

        // Make sure it's registered
        expect( view.hasMediator( mediatorName ), isTrue );

        // Remove Mediator
        view.removeMediator( mediatorName );

        // Make sure the View no longer knows about it
        expect( view.hasMediator( mediatorName ), isFalse );
      });

      test('registerObserver(), notifyObserver()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest5";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Register an Observer using this test
        // instance's viewTestMethod as the callback
        String noteName = "ViewTest5Note";
        mvc.IObserver observer = new mvc.Observer( viewTestMethod, this );
        view.registerObserver( noteName, observer );

        // Create a notification
        mvc.INotification note = new mvc.Notification( noteName );

        // Have the View notify the Observer
        view.notifyObservers( note );

        // Make sure the callback was executed
        expect( viewTestVar, equals(noteName) );
      });

      test('View calls onRegister()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest6";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Create a view component
        ViewTestViewComponent vc = new ViewTestViewComponent();

        // Register a ViewTestMediator
        mvc.IMediator mediator = new ViewTestMediator( vc );
        view.registerMediator( mediator );

        // Make sure it's registered
        expect( view.hasMediator( ViewTestMediator.NAME ), isTrue );

        // Make sure the Mediator's onRegister() method was called
        expect( vc.onRegisterCalled, isTrue );
      });

      test('View calls onRemove()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest7";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Create a view component
        ViewTestViewComponent vc = new ViewTestViewComponent();

        // Register a ViewTestMediator
        mvc.IMediator mediator = new ViewTestMediator( vc );
        view.registerMediator( mediator );

        // Make sure it's registered
        expect( view.hasMediator( ViewTestMediator.NAME ), isTrue );

        // Remove the Mediator
        view.removeMediator( ViewTestMediator.NAME );

        // Make sure the Mediator's onRemove() method was called
        expect( vc.onRemoveCalled, isTrue );
      });

      test('View calls listNotificationInterests()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest8";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Create a view component
        ViewTestViewComponent vc = new ViewTestViewComponent();

        // Register a ViewTestMediator
        mvc.IMediator mediator = new ViewTestMediator( vc );
        view.registerMediator( mediator );

        // Make sure the Mediator's listNotificationInterests() method was called
        expect( vc.listNotificationInterestsCalled, isTrue );
      });

      test('View calls handleNotification()', () {
        // Get a unique multiton instance of View
        String multitonKey = "ViewTest9";
        mvc.IView view = mvc.View.getInstance( multitonKey );

        // Create a view component
        ViewTestViewComponent vc = new ViewTestViewComponent();

        // Register a ViewTestMediator
        mvc.IMediator mediator = new ViewTestMediator( vc );
        view.registerMediator( mediator );

        // Create a Notification
        mvc.INotification note = new mvc.Notification( ViewTestNotes.NOTE_2 );

        // Send the Notification
        view.notifyObservers( note );

        // Make sure the Mediator's listNotificationInterests() method was called
        expect( vc.handleNotificationCalled, isTrue );
      });
    });
  }

  // A callback method for the test Observer
  void viewTestMethod( mvc.INotification note ) {
    viewTestVar = note.getName();
  }

  String viewTestVar;

  run() {
    _tests();
  }
}

class ViewTestNotes {

  static String NOTE_1 = "ViewTest/note/name/1";
  static String NOTE_2 = "ViewTest/note/name/2";
  static String NOTE_3 = "ViewTest/note/name/3";
}

class ViewTestViewComponent
{
  bool onRegisterCalled = false;
  bool onRemoveCalled = false;
  bool listNotificationInterestsCalled = false;
  bool handleNotificationCalled = false;
}

class ViewTestMediator extends mvc.Mediator
{
  // Name Mediator will be registered as
  static String NAME = "ViewTestMediator";

  // Constructor
  ViewTestMediator( ViewTestViewComponent viewComponent ):super( NAME, viewComponent ){}

  // Accessors that cast viewComponent to the correct type for this Mediator
  ViewTestViewComponent get vc { return viewComponent; }
  void set vc( ViewTestViewComponent viewTestViewComponent ) { viewComponent = viewTestViewComponent; }

  // Called when Mediator is registered
  void onRegister()
  {
    vc.onRegisterCalled = true;
  }

  // Also called when Mediator is registered
  List<String> listNotificationInterests()
  {
    vc.listNotificationInterestsCalled = true;
    return [ ViewTestNotes.NOTE_1,
             ViewTestNotes.NOTE_2,
             ViewTestNotes.NOTE_3 ];
  }

  // Called when a notification this Mediator is interested in is sent
  void handleNotification( mvc.INotification note )
  {
    vc.handleNotificationCalled = true;
  }

  // Called when Mediator is removed
  void onRemove()
  {
    vc.onRemoveCalled = true;
  }
}


<|start_filename|>lib/src/patterns/observer/Notification.dart<|end_filename|>
part of puremvc;

/**
 * A base [INotification] implementation.
 *
 * The Observer Pattern as implemented within PureMVC exists
 * to support publish/subscribe communication between actors.
 *
 * [INotification]s are not meant to be a replacement for [Event]s,
 * but rather an internal communication mechanism that ensures
 * PureMVC is portable regardless of what type of Event mechanism
 * is supported (or not) on a given platform.
 *
 * Generally, [IMediator] implementors place [Event] listeners on
 * their view components, and [IProxy] implementors place [Event]
 * listeners on service components. Those [Event]s are then handled in
 * the usual way, and may lead to the broadcast of [INotification]s
 * that trigger [ICommand]s or notify [IMediator]s.
 *
 * See [IView], [IObserver], [Notification]
 */
class Notification implements INotification
{
    /**
     * Constructor.
     *
     * -  Param [name] - name of the [INotification].
     * -  Param [body] - the [INotification] body. (optional)
     * -  Param [type] - the type of the [INotification] (optional)
     */
    Notification( String this.name, [dynamic this.body, String this.type] ){}

    /**
     * Get the [name] of the [INotification].
     *
     * -  Returns [String] - the name of the [INotification].
     */
    String getName()
    {
        return name;
    }

    /**
     * Set the [body] of the [INotification].
     *
     * -  Param [body] - the body of the [INotification].
     */
    void setBody( dynamic bodyObject )
    {
        body = bodyObject;
    }

    /**
     * Get the [body] of the [INotification].
     *
     * -  Returns [Dynamic] - the body of the [INotification].
     */
    dynamic getBody()
    {
        return body;
    }

    /**
     * Set the [type] of the [INotification].
     *
     * -  Param [type] - the type of the [INotification].
     */
    void setType( String noteType )
    {
        type = noteType;
    }

    /**
     * Get the [type] of the [INotification].
     *
     * -  Returns [String] - the type of the [INotification].
     */
    String getType()
    {
        return type;
    }

    /**
     * This [INotifications]'s [name]
     */
    String name;

    /**
     * This [INotifications]'s [type]
     */
    String type;

    /**
     * This [INotifications]'s [body]
     */
    dynamic body;

}


<|start_filename|>lib/src/interfaces/INotifier.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC [Notifier].
 *
 * [MacroCommand], [SimpleCommand], [Mediator] and [Proxy]
 * all have a need to send [Notification]s.
 *
 * The [INotifier] interface provides a common method called
 * [sendNotification] that relieves implementation code of
 * the necessity to actually construct [INotification]s.
 *
 * The [Notifier] class, which all of the above mentioned classes
 * extend, also provides an initialized reference to the [Facade]
 * Multiton, which is required for the convienience method
 * for sending [Notification]s, but also eases implementation as these
 * classes have frequent [IFacade] interactions and usually require
 * access to the facade anyway.
 *
 * See [IFacade], [INotification]
 */
abstract class INotifier {

  /**
   * Send an [INotification].
   *
   * Convenience method to prevent having to construct new
   * [INotification] instances in our implementation code.
   *
   * -  Param [noteName] the name of the note to send
   * -  Param [body] - the body of the note (optional)
   * -  Param [type] - the type of the note (optional)
   */
  void sendNotification( String noteName, [dynamic body, String type] );

  /**
   * Initialize this [INotifier] instance.
   *
   * This is how a [INotifier] gets its [multitonKey].
   * Calls to [sendNotification] or access to the
   * [facade] will fail until after this method
   * has been called.
   *
   * -  Param [key] - the Multiton key for this [INotifier].
   */
  void initializeNotifier( String key );

  /**
   * This INotifier's Multiton Key
   */
  void set multitonKey( String key );
  String get multitonKey;

}


<|start_filename|>test/Test_Observer.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_Observer
{
  _tests()
  {
    group('Observer', ()
    {
      test('Constructor null args', () {
        // Create a blind Observer
        mvc.IObserver observer = new mvc.Observer( null, null );

        // Make sure Observer was created
        expect( observer, isNotNull );
      });

      test('Constructor complete args', () {
        // Create an observer with callback method and caller instance defined
        mvc.IObserver observer = new mvc.Observer( this.observerTestMethod, this );

        // Make sure the Observer was created
        expect( observer, isNotNull  );

        // Make sure caller and callback were set
        expect( observer.getNotifyMethod(), isNotNull  );
        expect( observer.notifyMethod, isNotNull  );
        expect( observer.getNotifyContext(), isNotNull  );
        expect( observer.notifyContext, isNotNull  );

      });

      test('Constructor minimum args', () {
        // Create an Observer with callack only
        mvc.IObserver observer = new mvc.Observer( this.observerTestMethod );

        // Make sure Observer was created
        expect( observer, isNotNull  );

        // Make sure callback method was set
        expect( observer.getNotifyMethod(), isNotNull );
      });

      test('setNotifyMethod()', () {
        // Create an Observer
        mvc.IObserver observer = new mvc.Observer( null );

        // Call setNotifyMethod()
        observer.setNotifyMethod( observerTestMethod );

        // Make sure callback method was set
        expect( observer.getNotifyMethod(), isNotNull );
        expect( observer.notifyMethod, isNotNull );

      });

      test('setNotifyContext()', () {
        // Create an Observer
        mvc.IObserver observer = new mvc.Observer( null );

        // Call setNotifyContext()
        observer.setNotifyContext( this );

        // Make sure caller was set
        expect( observer.getNotifyContext(), isNotNull );
        expect( observer.getNotifyContext(), same(this) );
        expect( observer.notifyContext, isNotNull );
        expect( observer.notifyContext, same(this) );
      });

      test('compareNotifyContext()', () {
        // Create an Observer with only a caller
        mvc.IObserver observer = new mvc.Observer( null, this );

        // Make sure the caller was set
        expect( observer.compareNotifyContext( this ), isTrue );
      });

      test('notifyObserver()', () {
        // Create an Observer with this test instance's observerTestMethod() as the callback
        mvc.IObserver observer = new mvc.Observer( this.observerTestMethod, this );

        // Create a Notification
        String name = "Test";
        mvc.INotification note = new mvc.Notification( name );

        // Notify the Observer
        observer.notifyObserver( note );

        // Make sure the Observer was notified
        expect( observerTestNote, isNotNull );
        expect( observerTestNote.name, equals(name) );
      });
    });
  }

  // Test Notification
  mvc.INotification observerTestNote;

  // Callback method for Observer
  observerTestMethod( mvc.INotification note ){
    observerTestNote = note;
  }

  run() {
    _tests();
  }
}


<|start_filename|>example/Framework_Verify.html<|end_filename|>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>PureMVC - Framework Verification Page</title>
    <link rel="stylesheet" href="Framework_Verify.css">
  </head>
  <body>
    <h1>PureMVC MultiCore Framework for Dart</h1>
    <h2>Framework Verification Page</h2>
    This page just peforms few quick checks to see that the framework is working in your environment.<br/>

    <div id="container">
      <p id="text"></p>
    </div>

    <script src="packages/browser/dart.js"></script>
    <script type="application/dart" src="Framework_Verify.dart"/>
  </body>
</html>


<|start_filename|>lib/src/core/View.dart<|end_filename|>
part of puremvc;

/**
 * A PureMVC MultiCore [IView] implementation.
 *
 * In PureMVC, [IView] implementors assume these responsibilities:
 *
 * -  Maintain a cache of [IMediator] instances.
 * -  Provide methods for registering, retrieving, and removing [IMediator]s.
 * -  Managing the [IObserver] lists for each [INotification].
 * -  Providing a method for attaching [IObserver]s to an [INotification]'s [IObserver] list.
 * -  Providing a method for broadcasting an [INotification] to each of the [IObserver]s in a list.
 * -  Notifying the [IObservers] of a given [INotification] when it broadcast.
 *
 * See [IMediator], [IObserver], [INotification]
 */
class View implements IView
{

  /**
   * Constructor.
   *
   * This [IView] implementation is a Multiton, so you should not call the constructor directly,
   * but instead call the static [getInstance] method.
   *
   * -  Throws [MultitonErrorViewExists] if instance for this Multiton key has already been constructed
   */
  View( String key )
  {
    if (instanceMap[ key ] != null) throw new MultitonErrorViewExists();
    multitonKey = key;
    instanceMap[ multitonKey ] = this;
    mediatorMap = new Map<String,IMediator>();
    observerMap = new Map<String,List<IObserver>>();
    initializeView();
  }

  /**
   * Initialize the Multiton View instance.
   *
   * Called automatically by the constructor, this is your opportunity to initialize the Multiton
   * instance in your subclass without overriding the constructor.
   */
  void initializeView(  ){}

  /**
   * [IView] Multiton Factory method.
   *
   * -  Returns the [IView] Multiton instance for the specified key.
   */
  static IView getInstance( String key )
  {
    if ( key == null || key == "" ) return null;
    if ( instanceMap == null ) instanceMap = new Map<String,IView>();
    if ( instanceMap[ key ] == null ) instanceMap[ key ] = new View( key );
    return instanceMap[ key ];
  }

  /**
   * Register an [IObserver] to be notified of [INotification]s with a given name.
   *
   * -  Param [noteName] - the name of the [INotification] to notify this [IObserver] of.
   * -  Param [observer] - the [IObserver] to register.
   */
  void registerObserver( String noteName, IObserver observer )
  {
    if( observerMap[ noteName ] == null ) {
      observerMap[ noteName ] = new List<IObserver>();
    }
    observerMap[ noteName ].add( observer );
  }

  /**
   * Notify the [IObserver]s for a particular [INotification].
   *
   * All previously attached [IObserver]s for this [INotification]'s
   * list are notified and are passed a reference to the [INotification] in
   * the order in which they were registered.
   *
   * -  Param [note] - the [INotification] to notify [IObservers] of.
   */
  void notifyObservers( INotification note )
  {
    // Get a reference to the observers list for this notification name
    List<IObserver> observers_ref = observerMap[ note.getName() ];
    if( observers_ref != null )
    {
      // Copy observers from reference array to working array,
      // since the reference array may change during the notification loop
      List<IObserver> observers = new List<IObserver>();
      IObserver observer;
      for (var i = 0; i < observers_ref.length; i++) {
        observer = observers_ref[ i ];
        observers.add( observer );
      }

      // Notify Observers from the working array
      for (var i = 0; i < observers.length; i++) {
          observer = observers[ i ];
          observer.notifyObserver( note );
      }
    }
  }

  /**
   * Remove an [IObserver] from the list for a given [INotification] name.
   *
   * -  Param [noteName] - which [IObserver] list to remove from.
   * -  Param [notifyContext] - remove [IObserver]s with this object as the [notifyContext].
   */
  void removeObserver( String noteName, Object notifyContext )
  {
      // the observer list for the notification under inspection
      List<IObserver> observers = observerMap[ noteName ];

      // find the observer for the notifyContext
      for ( var i=0; i<observers.length; i++ )
      {
          if ( observers[i].compareNotifyContext( notifyContext ) == true )
          {
              // there can only be one Observer for a given notifyContext
              // in any given Observer list, so remove it and break
              observers.remove(observers[i]);
              break;
          }
      }

      // Also, when a Notification's Observer list length falls to
      // zero, delete the notification key from the observer map
      if ( observers.length == 0 ) {
          observerMap[ noteName ] = null;
      }
  }

  /**
   * Register an [IMediator] instance with the [IView].
   *
   * Registers the [IMediator] so that it can be retrieved by name,
   * and interrogates the [IMediator] for its [INotification] interests.
   *
   * If the [IMediator] returns a list of [INotification]
   * names to be notified about, an [Observer] is created encapsulating
   * the [IMediator] instance's [handleNotification] method
   * and registering it as an [IObserver] for all [INotification]s the
   * [IMediator] is interested in.
   *
   * -  Param [mediator] - a reference to the [IMediator] instance.
   */
  void registerMediator( IMediator mediator )
  {
    // do not allow re-registration (you must call removeMediator first)
    if ( mediatorMap[ mediator.getName() ] != null ) return;

    // Initialize with multiton key
    mediator.initializeNotifier( multitonKey );

    // Register the Mediator for retrieval by name
    mediatorMap[ mediator.getName() ] = mediator;

    // Get Notification interests, if any.
    List<String> interests = mediator.listNotificationInterests();

    // Register Mediator as an observer for each notification of interests
    if ( interests.length > 0 )
    {
      // Create Observer referencing this mediator's handlNotification method
      IObserver observer = new Observer( mediator.handleNotification, mediator );

      // Register Mediator as Observer for its list of Notification interests
      for ( var i=0;  i<interests.length; i++ ) {
          registerObserver( interests[i],  observer );
      }
    }

    // alert the mediator that it has been registered
    mediator.onRegister();
  }

  /**
   * Retrieve an [IMediator] from the [IView].
   *
   * -  Param [mediatorName] - the name of the [IMediator] instance to retrieve.
   * -  Returns [IMediator] - the [IMediator] instance previously registered in this core with the given [mediatorName].
   */
  IMediator retrieveMediator( String mediatorName )
  {
      return mediatorMap[ mediatorName ];
  }

  /**
   * Remove an [IMediator] from the [IView].
   *
   * -  Param [mediatorName] - name of the [IMediator] instance to be removed.
   * -  Returns [IMediator] - the [IMediator] that was removed from this core's [IView].
   */
  IMediator removeMediator( String mediatorName )
  {
      // Retrieve the named mediator
      IMediator mediator = mediatorMap[ mediatorName ];

      if ( mediator != null )
      {
        // for every notification this mediator is interested in...
        List<String> interests = mediator.listNotificationInterests();
        for ( var i=0; i<interests.length; i++ )
        {
          // remove the observer linking the mediator
          // to the notification interest
          removeObserver( interests[i], mediator );
        }

        // remove the mediator from the map
        mediatorMap[ mediatorName ] = null;

        // alert the mediator that it has been removed
        mediator.onRemove();
      }

      return mediator;
  }

  /**
   * Check if an [IMediator] is registered with the [IView].
   *
   * -  Param [mediatorName] - the name of the [IMediator] you're looking for.
   * -  Returns [bool] - whether an [IMediator] is registered in this core with the given [mediatorName].
   */
  bool hasMediator( String mediatorName )
  {
      return mediatorMap[ mediatorName ] != null;
  }

  /**
   * Remove an [IView] Multiton instance.
   *
   * -  Param [key] - the Multiton key of [IView] instance to remove.
   */
  static void removeView( String key )
  {
      instanceMap[ key ] = null;
  }

  // Mapping of IMediator names to IMediator instances
  Map<String,IMediator> mediatorMap;

  // Mapping of INotification names to IObserver lists
  Map<String,List<IObserver>> observerMap;

  // Multiton IView instance map
  static Map<String,IView> instanceMap;

  // The Multiton key for this Core
  String multitonKey;
}

class MultitonErrorViewExists {
  const MultitonErrorViewExists();

  String toString() {
    return "IViewMultiton instance already constructed for this key.";
  }
}



<|start_filename|>test/Test_Controller.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_Controller
{
  _tests()
  {
    group('Controller', ()
    {
      test('getInstance()', () {
        // Get a unique multiton instance of Controller
        String multitonKey = "ControllerTest1";
        mvc.IController controller = mvc.Controller.getInstance( multitonKey );

        // Make sure a Controller instance was returned
        expect( controller, isNotNull );

        // Call getInstance() again
        mvc.IController again = mvc.Controller.getInstance( multitonKey );

        // Make sure the same Controller instance was returned
        expect( controller, same(again) );
      });

      test('registerCommand(), hasCommand()', () {
        // Get a unique multiton instance of Controller
        String multitonKey = "ControllerTest2";
        mvc.IController controller = mvc.Controller.getInstance( multitonKey );

        // Register a Command
        String noteName = "ControllerTest2Note";
        controller.registerCommand( noteName, () => new ControllerTestMacroCommand() );

        // Make sure it's registered
        expect( controller.hasCommand( noteName ), isTrue );
      });

      test('executeCommand() +SimpleCommand', () {
        // Get a unique multiton instance of Controller
        String multitonKey = "ControllerTest3";
        mvc.IController controller = mvc.Controller.getInstance( multitonKey );

        // Register a Command
        String noteName = "ControllerTest3Note";
        controller.registerCommand( noteName, () => new ControllerTestDoubleInputCommand() );

        // Create a Notification
        ControllerTestVO vo = new ControllerTestVO( 5 );
        mvc.INotification note = new mvc.Notification( noteName, vo );

        // Have the Controller execute the Command
        controller.executeCommand( note );

        // Make sure the Command executed
        expect( vo.doubled, equals(10) );
        expect( vo.squared, equals(null) );

      });

      test('executeCommand() +MacroCommand', () {
        // Get a unique multiton instance of Controller
        String multitonKey = "ControllerTest4";
        mvc.IController controller = mvc.Controller.getInstance( multitonKey );

        // Register a Command
        String noteName = "ControllerTest4Note";
        controller.registerCommand( noteName, () => new ControllerTestMacroCommand() );

        // Create a Notification
        ControllerTestVO vo = new ControllerTestVO( 5 );
        mvc.INotification note = new mvc.Notification( noteName, vo );

        // Have the Controller execute the Command
        controller.executeCommand( note );

        // Make sure the Command executed
        expect( vo.doubled, equals(10) );
        expect( vo.squared, equals(25) );

      });

      test('removeCommand()', () {
        // Get a unique multiton instance of Controller
        String multitonKey = "ControllerTest5";
        mvc.IController controller = mvc.Controller.getInstance( multitonKey );

        // Register a Command
        String noteName = "ControllerTest5Note";
        controller.registerCommand( noteName, () => new ControllerTestMacroCommand() );

        // Make sure it's registered
        expect( controller.hasCommand( noteName ), isTrue );

        // Remove the Command
        controller.removeCommand( noteName );

        // Make sur the Controller doesn't know about it any more
        expect( controller.hasCommand( noteName ), isFalse );
      });
    });
  }

  run() {
    _tests();
  }
}

class ControllerTestVO
{
  int input;
  int doubled;
  int squared;

  ControllerTestVO( int this.input ){}
}

class ControllerTestMacroCommand extends mvc.MacroCommand
{
  void initializeMacroCommand()
  {
    // add the subcommands
    addSubCommand( () => new ControllerTestDoubleInputCommand() );
    addSubCommand( () => new ControllerTestSquareInputCommand() );
  }
}

class ControllerTestDoubleInputCommand extends mvc.SimpleCommand
{
  void execute( mvc.INotification note )
  {
    // Get the VO from the note body
    ControllerTestVO vo = note.getBody();

    // compute the input doubled
    vo.doubled = vo.input * 2;
  }
}

class ControllerTestSquareInputCommand extends mvc.SimpleCommand
{
  void execute( mvc.INotification note )
  {
    // Get the VO from the note body
    ControllerTestVO vo = note.getBody();

    // Compute the input squared
    vo.squared = vo.input * vo.input;
  }
}

<|start_filename|>example/Framework_Verify.css<|end_filename|>

body {
  background-color: #F8F8F8;
  font-family: 'Open Sans', sans-serif;
  font-size: 14px;
  font-weight: normal;
  line-height: 2.0em;
  margin: 50px;
}

p {
  color: #333;
}

#container {
  width: 100%;
  height: 400px;
  position: relative;
  border: 1px solid #ccc;
  background-color: #fff;
}

#text {
  font-size: 16pt;
  text-align: left;
  margin-top: 10px;
  margin-left:25px;
}


<|start_filename|>lib/src/interfaces/IController.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC MultiCore Controller.
 *
 * In PureMVC, an [IController] implementor
 * follows the 'Command and Controller' strategy, and
 * assumes these responsibilities:
 *
 * -  Remembering which [ICommand]s are intended to handle which [INotification]s.
 * -  Registering itself as an [IObserver] with the [View] for each [INotification] that it has an [ICommand] mapping for.
 * -  Creating a new instance of the proper [ICommand] to handle a given [INotification] when notified by the [IView].
 * -  Calling the [ICommand]'s [execute] method, passing in the [INotification].
 *
 * See [INotification], [ICommand]
 */
abstract class IController
{
  /**
   * Register an [INotification] to [ICommand] mapping with the [IController].
   *
   * -  Param [noteName] - the name of the [INotification] to associate the [ICommand] with.
   * -  Param [commandFactory] - a function that creates a new instance of the [ICommand].
   */
  void registerCommand( String notificationName, Function commandFactory );

  /**
   * Execute the [ICommand] previously registered as the
   * handler for [INotification]s with the given notification's name.
   *
   * -  Param [note] - the [INotification] to execute the associated [ICommand] for
   */
  void executeCommand( INotification note );

  /**
   * Remove a previously registered [INotification] to [ICommand] mapping from the [IController].
   *
   * -  Param [noteName] - the name of the [INotification] to remove the [ICommand] mapping for.
   */
  void removeCommand( String noteName );

  /**
   * Check if an [ICommand] is registered for a given [INotification] name with the [IController].
   *
   * -  Param [noteName] - the name of the [INotification].
   * -  Returns [bool] - whether an [ICommand] is currently registered for the given [noteName].
   */
  bool hasCommand( String noteName );

  /**
   * This IController's Multiton Key
   */
  void set multitonKey( String key );
  String get multitonKey;

}


<|start_filename|>test/Test_Model.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_Model
{
  _tests()
  {
    group('Model', ()
    {
      test('getInstance()', () {
        // Unique multiton instance of Model
        String multitonKey = "ModelTest1";
        mvc.IModel model = mvc.Model.getInstance( multitonKey );
        expect( model, isNotNull );

        // Same instance retrieved again
        mvc.IModel again = mvc.Model.getInstance( multitonKey );
        expect( model, same(again) );
      });

      test('registerProxy(), hasProxy()', () {
        // Unique multiton instance of Model
        String multitonKey = "ModelTest2";
        mvc.IModel model = mvc.Model.getInstance( multitonKey );

        // Register a Proxy
        String proxyName = "ModelTest2Proxy";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );
        model.registerProxy( proxy );

        // Make sure it's there
        expect( model.hasProxy( proxyName ), isTrue );
      });

      test('retrieveProxy()', () {
        // Unique multiton instance of Model
        String multitonKey = "ModelTest3";
        mvc.IModel model = mvc.Model.getInstance( multitonKey );

        // Register a Proxy
        String proxyName = "ModelTest3Proxy";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );
        model.registerProxy( proxy );

        // Make sure same Proxy is retrieved
        expect( model.retrieveProxy( proxyName ), same(proxy) );
      });

      test('removeProxy(), hasProxy()', () {
        // Unique multiton instance of Model
        String multitonKey = "ModelTest4";
        mvc.IModel model = mvc.Model.getInstance( multitonKey );

        // Register a Proxy
        String proxyName = "ModelTest4Proxy";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );
        model.registerProxy( proxy );

        // Make sure it is returned when removed
        expect( model.removeProxy( proxyName ), same(proxy) );

        // Make sure Model doesn't know about it anymore
        expect( model.hasProxy( proxyName ), isFalse );
      });

      test('Model calls onRegister()', () {
        // Unique multiton instance of Model
        String multitonKey = "ModelTest5";
        mvc.IModel model = mvc.Model.getInstance( multitonKey );

        // Register a Proxy
        mvc.IProxy proxy = new ModelTestProxy();
        model.registerProxy( proxy );

        // Make sure the Model calls the Proxy's onRegister() method
        expect( proxy.getData(), equals(ModelTestProxy.ON_REGISTER_CALLED) );
      });

      test('Model calls onRemove()', () {
        // Unique multiton instance of Model
        String multitonKey = "ModelTest6";
        mvc.IModel model = mvc.Model.getInstance( multitonKey );

        // Register a Proxy
        mvc.IProxy proxy = new ModelTestProxy();
        model.registerProxy( proxy );

        // Remove the Proxy
        model.removeProxy( ModelTestProxy.NAME );

        // Make sure the Model calls the Proxy's onRemove() method
        expect( proxy.getData(), equals(ModelTestProxy.ON_REMOVE_CALLED) );
      });
    });
  }

  run() {
    _tests();
  }
}

class ModelTestProxy extends mvc.Proxy
{
  static String NAME = "ModelTestProxyClass";
  static String FRESH = "Fresh Instance";
  static String ON_REGISTER_CALLED = "onRegister() Called";
  static String ON_REMOVE_CALLED = "onRemove() Called";

  ModelTestProxy():super( NAME ){
    setData( FRESH );
  }

  void onRegister()
  {
    setData( ON_REGISTER_CALLED );
  }

  void onRemove()
  {
    setData( ON_REMOVE_CALLED );
  }
}


<|start_filename|>lib/src/interfaces/IMediator.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC MultiCore Mediator.
 *
 * In PureMVC, [IMediator] implementors assume these responsibilities:
 *
 * -  Implement a common method which returns a list of all [INotification]s the [IMediator] has interest in.
 * -  Implement a notification (callback) method for handling [INotification]s.
 * -  Implement methods that are called when the [IMediator] is registered or removed from an [IView].
 *
 * Additionally, [IMediator]s typically:
 *
 * -  Act as an intermediary between one or more view components and the rest of the application.
 * -  Place [Event] listeners on view components, and implement handlers which often send [INotification]s or interact with [IProxy]s to post or retrieve data.
 * -  Receive [INotification]s, (typically containing data) and updating view components in response.
 *
 * When an [IMediator] is registered with the [IView], the [IMediator]'s [listNotificationInterests] method is called
 * The [IMediator] will return a [List] of [INotification] names which it wishes to be notified about.
 *
 * The [IView] will then create an [IObserver] object encapsulating that [IMediator]'s and its [handleNotification] method
 * and register the [IObserver] for each [INotification] name returned by the [IMediator]'s [listNotificationInterests] method.
 *
 * See [INotification], [IView]
 */
abstract class IMediator extends INotifier
{

  /**
   * Get the [IMediator] instance's [name].
   *
   * -  Returns [String] - the [IMediator] instance's [name].
   */
  String getName();

  /**
   * Get the [IMediator]'s [viewComponent].
   *
   * -  Returns [Dynamic] - the View Component
   */
  dynamic getViewComponent();

  /**
   * Set the [IMediator]'s [viewComponent].
   *
   * -  Param [Dynamic] - the [viewComponent].
   */
  void setViewComponent( dynamic viewComponent );

  /**
   * List [INotification] interests.
   *
   * -  Returns [List] - a [List] of the [INotification] names this [IMediator] has an interest in.
   */
  List<String> listNotificationInterests( );

  /**
   * Handle an [INotification].
   *
   * -  Param [note] - the [INotification] to be handled.
   */
  void handleNotification( INotification note );

  /**
   * Called by the [IView] when the [IMediator] is registered.
   */
  void onRegister( );

  /**
   * Called by the [IView] when the [IMediator] is removed.
   */
  void onRemove( );


  /**
   * This [IMediator]'s [viewComponent].
   */
  void set viewComponent( dynamic viewComponent );
  dynamic get viewComponent;

  /**
   * This [IMediator]'s [name].
   */
  void set name( String mediatorName );
  String get name;

}

<|start_filename|>lib/src/interfaces/IModel.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC MultiCore Model.
 *
 * In PureMVC, [IModel] implementors provide access to [IProxy] objects by named lookup.
 *
 * An [IModel] assumes these responsibilities:
 *
 * -  Maintain a cache of [IProxy] instances.
 * -  Provide methods for registering, retrieving, and removing [IProxy] instances.
 *
 * Your application must register [IProxy] instances
 * with the [IModel]. Typically, you use an
 * [ICommand] to create and register [IProxy]
 * instances once the [IFacade] has initialized the core
 * actors.
 *
 * See [IProxy], [IFacade]
 */
abstract class IModel
{
    /**
     * Register an [IProxy] instance with the [IModel].
     *
     * -  Param [proxy] - an object reference to be held by the [IModel].
     */
	void registerProxy( IProxy proxy );

    /**
     * Retrieve an [IProxy] instance from the [IModel].
     *
     * -  Param [proxyName] - the name of the [IProxy] instance to retrieve.
     * -  Returns the [IProxy] instance previously registered with the given [proxyName].
     */
    IProxy retrieveProxy( String proxyName );

    /**
     * Remove an [IProxy] instance from the [IModel].
     *
     * -  Param [proxyName] - name of the [IProxy] instance to be removed.
     * -  Returns [IProxy] - the [IProxy] that was removed from the [IModel].
     */
    IProxy removeProxy( String proxyName );

    /**
     * Check if an [IProxy] is registered with the [IModel].
     *
     * -  Param [proxyName] - the name of the [IProxy] instance you're looking for.
     * -  Returns [bool] - whether an [IProxy] is currently registered with the given [proxyName].
     */
    bool hasProxy( String proxyName );

    /**
     * This [IModel]'s Multiton Key
     */
    void set multitonKey( String key );
    String get multitonKey;

}


<|start_filename|>lib/src/patterns/observer/Notifier.dart<|end_filename|>
part of puremvc;

/**
 * A Base [INotifier] implementation.
 *
 * [MacroCommand], [SimpleCommand], [Mediator], and [Proxy]
 * all have a need to send [Notifications].
 *
 * The [INotifier] interface provides a common method called
 * [sendNotification] that relieves implementation code of
 * the necessity to actually construct [INotification]s.
 *
 * The [Notifier] class, which all of the above mentioned classes
 * extend, provides an initialized reference to an [IFacade]
 * Multiton, which is required by the convienience method
 * for sending [INotification]s, but also eases implementation as these
 * classes have frequent [Facade] interactions and usually require
 * access to the facade anyway.
 *
 * NOTE: In the MultiCore version of the framework, there is one caveat to
 * [Notifier]s, they cannot send notifications or reach the facade until they
 * have a valid multitonKey.
 *
 * The multitonKey is set:
 *   * on a [ICommand] when it is instantiated by the [Controller]
 *   * on a [IMediator] when it is registered with the [IView]
 *   * on a [IProxy] when it is registered with the [IModel]
 *
 * See [Proxy], [Facade], [Mediator], [MacroCommand], [SimpleCommand]
 */
class Notifier implements INotifier
{

    Notifier(){

    }

    /**
     * Send an [INotification].
     *
     * Convenience method to prevent having to construct new
     * [INotification] instances in our implementation code.
     *
     * -  Param [noteName] the name of the note to send
     * -  Param [body] - the body of the note (optional)
     * -  Param [type] - the type of the note (optional)
     */
    void sendNotification( String noteName, [dynamic body, String type] )
    {
        if (facade != null) {
            facade.sendNotification( noteName, body, type );
        }
    }

    /**
     * Initialize this [INotifier] instance.
     *
     * This is how a [INotifier] gets its [multitonKey].
     * Calls to [sendNotification] or access to the
     * [facade] will fail until after this method
     * has been called.
     *
     * -  Param [key] - the Multiton key for this [INotifier].
     */
    void initializeNotifier( String key )
    {
        multitonKey = key;
    }

    /**
     *  Return the Multiton Facade instance
     *  -  Throws [MultitonErrorNotifierLacksKey] if no multitonKey is set. Usually means facade getter is being accessed before initializeNotifier has been called (i.e., from the constructor). Defer facade access until the onRegister method.
     */
    IFacade get facade
    {
        if ( multitonKey == null ) throw new MultitonErrorNotifierLacksKey( );
        return Facade.getInstance( multitonKey );
    }

    // The Multiton Key for this app
    String multitonKey;
}

class MultitonErrorNotifierLacksKey {
  const MultitonErrorNotifierLacksKey();

  String toString() {
    return "multitonKey for this Notifier not yet initialized!";
  }
}

<|start_filename|>test/Test_SimpleCommand.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_SimpleCommand
{
  _tests()
  {
    group('SimpleCommand', ()
    {
      test('Constructor', () {
        // Create a SimpeCommand
        mvc.ICommand simpleCommand = new SimpleCommandTestDoubleInputCommand();
        expect( simpleCommand, isNotNull  );
      });

      test('execute()', () {
        // Create a SimpeCommand
        mvc.ICommand simpleCommand = new SimpleCommandTestDoubleInputCommand();

        // Crete a VO and a Notification to pass it to the Command with
        SimpleCommandTestVO vo = new SimpleCommandTestVO( 5 );
        mvc.INotification note = new mvc.Notification( "SimpleCommandTestNote", vo );

        // Execute the SimpleCommand with the note
        simpleCommand.execute( note );

        // Make sure the SimpleCommand logic was executed
        expect( vo.result, equals(10) );
      });

      test('initializeNotifier()', () {
        // Create a SimpleCommand
        mvc.INotifier notifier = new SimpleCommandTestDoubleInputCommand();

        // call initializeNotifier()
        String multitonKey = "SimpleCommandTest";
        notifier.initializeNotifier( multitonKey );

        // Make sure the SimpleCommand's multitonKey was set
        expect( notifier.multitonKey, isNotNull );
      });
    });
  }

  run() {
    _tests();
  }
}

class SimpleCommandTestVO
{
  SimpleCommandTestVO( int this.input ) {
  }

  int input;
  int result;
}

class SimpleCommandTestDoubleInputCommand extends mvc.SimpleCommand
{
  void execute( mvc.INotification note )
  {
    // Get the VO from the note
    SimpleCommandTestVO vo = note.getBody();

    // Fabricate a result
    vo.result = 2 * vo.input;
  }
}

<|start_filename|>test/Unit_Tests.html<|end_filename|>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>PureMVC MultiCore Framework for Dart - Unit Tests</title>
    <link rel="stylesheet" href="Unit_Tests.css">
  </head>
  <body>
    <h1>PureMVC MultiCore Framework for Dart</h1>
    <h2>Framework Unit Tests</h2>

    <div id="container">
     <table id="outputTable">
    	<TR><th id="status" colspan='4' align='left'>Starting Dart unit test framework...</th></TR>
    	<TR id="result"></TR>
   	 </table>
    </div>

     <script src="packages/browser/dart.js"></script>
    <script type="application/dart" src="Unit_Tests.dart"></script>
  </body>
</html>


<|start_filename|>lib/src/patterns/proxy/Proxy.dart<|end_filename|>
part of puremvc;

/**
 * A base [IProxy] implementation.
 *
 * In PureMVC, [IProxy] implementors assume these responsibilities:
 *
 * -  Implement a common method which returns the name of the [IProxy].
 * -  Provide methods for setting and getting a Data Object.
 *
 * Additionally, [IProxy]s typically:
 *
 * -  Provide methods for manipulating the Data Object and referencing it by type.
 * -  Generate [INotification]s when their Data Object changes.
 * -  Expose their name as a [static final String] called [NAME].
 * -  Encapsulate interaction with local or remote services used to fetch and persist data.
 *
 * See [IModel]
 */
class Proxy extends Notifier implements IProxy
{
    /**
     * Constructor
     *
     * -  Param [name] - the [name] this [IProxy] will be registered with.
     * -  Param [data] - the Data Object (optional)
     */
    Proxy( String this.name, [dynamic this.data] ){ }

    /**
     * Get the [IProxy] [name].
     *
     * -  Returns [String] - the [IProxy] instance [name].
     */
    String getName()
    {
        return name;
    }

    /**
     * Set the [dataObject].
     *
     * -  Param [Dynamic] - the [dataObject] this [IProxy] will tend.
     */
    void setData( dynamic dataObject )
    {
       data = dataObject;
    }

    /**
     * Get the [dataObject].
     *
     * -  Returns [Dynamic] - the [dataObject].
     */
    dynamic getData()
    {
        return data;
    }

    /**
     * Called by the [IModel] when the [IProxy] is registered.
     *
     * Override in your subclass and add code to be run at registration time.
     */
    void onRegister(){}

    /**
     * Called by the [IModel] when the [IProxy] is removed
     */
    void onRemove(){}

    /**
     * This [IProxy]'s [name].
     */
    String name;

    /**
     * This [IProxy]'s [dataObject].
     */
    dynamic data;

}


<|start_filename|>test/Test_Facade.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_Facade
{
  _tests()
  {
    // Test the Facade specific functionality
    group('Facade::IFacade', ()
    {
      test('getInstance()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Make sure a Facade instance was returned
        expect( facade, isNotNull );

        // Call getInstance() again
        mvc.IFacade again = mvc.Facade.getInstance( multitonKey );

        // Make sure the same Facade instance was returned
        expect( facade, same(again) );

        // Make sure the Facade's multitonKey was set
        expect( facade.multitonKey, equals(multitonKey) );

        // Make sure the Model was created
        expect( facade.model, isNotNull );

        // Make sure the Model's multitonKey was set
        expect( facade.model.multitonKey, equals(multitonKey) );

        // Make sure the View was created
        expect( facade.view, isNotNull );

        // Make sure the View's multitonKey was set
        expect( facade.view.multitonKey, equals(multitonKey) );

        // Make sure the Controller was created
        expect( facade.controller, isNotNull );

        // Make sure the Controller's multitonKey was set
        expect( facade.controller.multitonKey, equals(multitonKey) );
      });

      test('getInstance(), hasCore()', () {

        // Make sure it's not reported as registered first
        String multitonKey = "FacadeTest0";
        expect( mvc.Facade.hasCore( multitonKey ), isFalse );

        // Get a unique multiton instance of Facade
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Make sure it's registered
        expect( mvc.Facade.hasCore( multitonKey ), isTrue );
      });

      test('removeCore(), hasCore()', () {

        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest1";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Make sure it's registered
        expect( mvc.Facade.hasCore( multitonKey ), isTrue );

        // Remove the core
        mvc.Facade.removeCore(multitonKey);

        // Make sure the core is no longer registered
        expect( mvc.Facade.hasCore( multitonKey ), isFalse );
      });
    });

    // Test the Facade's IController interface functionality
    group('Facade::IController', ()
    {
      test('registerCommand(), hasCommand()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest2";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Command
        String noteName = "FacadeTest2Note";
        facade.registerCommand( noteName, () => new FacadeTestMacroCommand() );

        // Make sure it's registered
        expect( facade.hasCommand( noteName ), isTrue );
      });

      test('sendNotification() ->SimpleCommand', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest3";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Command
        String noteName = "FacadeTest3Note";
        facade.registerCommand( noteName, () => new FacadeTestDoubleInputCommand() );

        // Create a value object
        FacadeTestVO vo = new FacadeTestVO( 5 );

        // Have the Facade send the note, triggering the Command
        facade.sendNotification( noteName, vo );

        // Make sure the Command executed
        expect( vo.doubled, equals(10) );
        expect( vo.squared, equals(null) );
      });

      test('sendNotification() ->MacroCommand', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest4";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Command
        String noteName = "FacadeTest4Note";
        facade.registerCommand( noteName, () => new FacadeTestMacroCommand() );

        // Create a value object
        FacadeTestVO vo = new FacadeTestVO( 5 );

        // Have the Facade execute the Command
        facade.sendNotification( noteName, vo );

        // Make sure the Command executed
        expect( vo.doubled, equals(10) );
        expect( vo.squared, equals(25) );
      });

      test('removeCommand()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest5";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Command
        String noteName = "FacadeTest5Note";
        facade.registerCommand( noteName, () => new FacadeTestMacroCommand() );

        // Make sure it's registered
        expect( facade.hasCommand( noteName ), isTrue );

        // Remove the Command
        facade.removeCommand( noteName );

        // Make sur the Controller doesn't know about it any more
        expect( facade.hasCommand( noteName ), isFalse );
      });
    });

    // Test the Facade's IView interface functionality
    group('Facade::IView', ()
    {
      test('registerMediator(), hasMediator()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest6";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Mediator
        String mediatorName = "FacadeTest6Mediator";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );
        facade.registerMediator( mediator );

        // Make sure it's registered
        expect( facade.hasMediator( mediatorName ), isTrue );
      });

      test('retrieveMediator()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest7";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Mediator
        String mediatorName = "FacadeTest7Mediator";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );
        facade.registerMediator( mediator );

        // Make sure same mediator is retrieved
        expect( facade.retrieveMediator( mediatorName ), same(mediator) );
      });

      test('removeMediator()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest8";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Mediator
        String mediatorName = "FacadeTest8Mediator";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );
        facade.registerMediator( mediator );

        // Make sure it's registered
        expect( facade.hasMediator( mediatorName ), isTrue );

        // Remove Mediator
        facade.removeMediator( mediatorName );

        // Make sure the Facade no longer knows about it
        expect( facade.hasMediator( mediatorName ), isFalse );
      });

      test('registerObserver(), notifyObserver()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest8";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register an Observer using this test
        // instance's facadeTestMethod as the callback
        String noteName = "FacadeTest8Note";
        mvc.IObserver observer = new mvc.Observer( facadeTestMethod, this );
        facade.registerObserver( noteName, observer );

        // Create a notification
        mvc.INotification note = new mvc.Notification( noteName );

        // Have the Facade notify the Observer
        facade.notifyObservers( note );

        // Make sure the callback was executed
        expect( facadeTestVar, equals(noteName) );
      });

      test('registerMediator(), ->mediator.onRegister()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest9";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Create a view component
        FacadeTestViewComponent vc = new FacadeTestViewComponent();

        // Register a FacadeTestMediator
        mvc.IMediator mediator = new FacadeTestMediator( vc );
        facade.registerMediator( mediator );

        // Make sure it's registered
        expect( facade.hasMediator( FacadeTestMediator.NAME ), isTrue );

        // Make sure the Mediator's onRegister() method was called
        expect( vc.onRegisterCalled, isTrue );
      });

      test('removeMediator(), ->mediator.onRemove()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest10";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Create a view component
        FacadeTestViewComponent vc = new FacadeTestViewComponent();

        // Register a FacadeTestMediator
        mvc.IMediator mediator = new FacadeTestMediator( vc );
        facade.registerMediator( mediator );

        // Make sure it's registered
        expect( facade.hasMediator( FacadeTestMediator.NAME ), isTrue );

        // Remove the Mediator
        facade.removeMediator( FacadeTestMediator.NAME );

        // Make sure the Mediator's onRemove() method was called
        expect( vc.onRemoveCalled, isTrue );
      });

      test('registerMediator(), ->mediator.listNotificationInterests()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest11";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Create a view component
        FacadeTestViewComponent vc = new FacadeTestViewComponent();

        // Register a FacadeTestMediator
        mvc.IMediator mediator = new FacadeTestMediator( vc );
        facade.registerMediator( mediator );

        // Make sure the Mediator's listNotificationInterests() method was called
        expect( vc.listNotificationInterestsCalled, isTrue );
      });

      test('sendNotification(), ->handleNotification()', () {
        // Get a unique multiton instance of Facade
        String multitonKey = "FacadeTest12";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Create a view component
        FacadeTestViewComponent vc = new FacadeTestViewComponent();

        // Register a FacadeTestMediator
        mvc.IMediator mediator = new FacadeTestMediator( vc );
        facade.registerMediator( mediator );

        // Send the Notification
        facade.sendNotification( FacadeTestNotes.NOTE_2  );

        // Make sure the Mediator's listNotificationInterests() method was called
        expect( vc.handleNotificationCalled, isTrue );
      });
    });

    // Test the Facade's IModel interface functionality
    group('Facade::IModel', ()
    {
      test('registerProxy(), hasProxy()', () {
        // Unique multiton instance of Facade
        String multitonKey = "FacadeTest13";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Proxy
        String proxyName = "FacadeTest13Proxy";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );
        facade.registerProxy( proxy );

        // Make sure it's there
        expect( facade.hasProxy( proxyName ), isTrue );
      });

      test('retrieveProxy()', () {
        // Unique multiton instance of Facade
        String multitonKey = "FacadeTest14";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Proxy
        String proxyName = "FacadeTest14Proxy";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );
        facade.registerProxy( proxy );

        // Make sure same Proxy is retrieved
        expect( facade.retrieveProxy( proxyName ), same(proxy) );
      });

      test('removeProxy(), hasProxy()', () {
        // Unique multiton instance of Facade
        String multitonKey = "FacadeTest15";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Proxy
        String proxyName = "FacadeTest15Proxy";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );
        facade.registerProxy( proxy );

        // Make sure it is returned when removed
        expect( facade.removeProxy( proxyName ), same(proxy) );

        // Make sure Facade doesn't know about it anymore
        expect( facade.hasProxy( proxyName ), isFalse );
      });

      test('registerProxy(), ->proxy.onRegister()', () {
        // Unique multiton instance of Facade
        String multitonKey = "FacadeTest16";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Proxy
        mvc.IProxy proxy = new FacadeTestProxy();
        facade.registerProxy( proxy );

        // Make sure the Proxy's onRegister() method is called
        expect( proxy.getData(), equals(FacadeTestProxy.ON_REGISTER_CALLED) );
      });

      test('removeProxy(), ->proxy.onRemove()', () {
        // Unique multiton instance of Facade
        String multitonKey = "FacadeTest17";
        mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );

        // Register a Proxy
        mvc.IProxy proxy = new FacadeTestProxy();
        facade.registerProxy( proxy );

        // Remove the Proxy
        facade.removeProxy( FacadeTestProxy.NAME );

        // Make sure the Proxy's onRemove() method is called
        expect( proxy.getData(), equals(FacadeTestProxy.ON_REMOVE_CALLED) );
      });
    });
  }

  run() {
    _tests();
  }
}

// A callback method for the test Observer
void facadeTestMethod( mvc.INotification note ) {
  facadeTestVar = note.getName();
}

String facadeTestVar;

class FacadeTestNotes {

  static String NOTE_1 = "FacadeTest/note/name/1";
  static String NOTE_2 = "FacadeTest/note/name/2";
  static String NOTE_3 = "FacadeTest/note/name/3";
}

class FacadeTestViewComponent
{
  bool onRegisterCalled = false;
  bool onRemoveCalled = false;
  bool listNotificationInterestsCalled = false;
  bool handleNotificationCalled = false;
}

class FacadeTestMediator extends mvc.Mediator
{
  // Name Mediator will be registered as
  static String NAME = "FacadeTestMediator";

  // Constructor
  FacadeTestMediator( FacadeTestViewComponent viewComponent ):super( NAME, viewComponent ){}

  // Accessors that cast viewComponent to the correct type for this Mediator
  FacadeTestViewComponent get vc { return viewComponent; }
  void set vc( FacadeTestViewComponent facadeTestViewComponent ) { viewComponent = facadeTestViewComponent; }

  // Called when Mediator is registered
  void onRegister()
  {
    vc.onRegisterCalled = true;
  }

  // Also called when Mediator is registered
  List<String> listNotificationInterests()
  {
    vc.listNotificationInterestsCalled = true;
    return [ FacadeTestNotes.NOTE_1,
             FacadeTestNotes.NOTE_2,
             FacadeTestNotes.NOTE_3 ];
  }

  // Called when a notification this Mediator is interested in is sent
  void handleNotification( mvc.INotification note )
  {
    vc.handleNotificationCalled = true;
  }

  // Called when Mediator is removed
  void onRemove()
  {
    vc.onRemoveCalled = true;
  }
}

class FacadeTestProxy extends mvc.Proxy
{
  static String NAME = "FacadeTestProxyClass";
  static String FRESH = "Fresh Instance";
  static String ON_REGISTER_CALLED = "onRegister() Called";
  static String ON_REMOVE_CALLED = "onRemove() Called";

  FacadeTestProxy():super( NAME ){
    setData( FRESH );
  }

  void onRegister()
  {
    setData( ON_REGISTER_CALLED );
  }

  void onRemove()
  {
    setData( ON_REMOVE_CALLED );
  }
}

class FacadeTestVO
{
  int input;
  int doubled;
  int squared;

  FacadeTestVO( int this.input ){}
}

class FacadeTestMacroCommand extends mvc.MacroCommand
{
  void initializeMacroCommand()
  {
    // add the subcommands
    addSubCommand( () => new FacadeTestDoubleInputCommand() );
    addSubCommand( () => new FacadeTestSquareInputCommand() );
  }
}

class FacadeTestDoubleInputCommand extends mvc.SimpleCommand
{
  void execute( mvc.INotification note )
  {
    // Get the VO from the note body
    FacadeTestVO vo = note.getBody();

    // compute the input doubled
    vo.doubled = vo.input * 2;
  }
}

class FacadeTestSquareInputCommand extends mvc.SimpleCommand
{
  void execute( mvc.INotification note )
  {
    // Get the VO from the note body
    FacadeTestVO vo = note.getBody();

    // Compute the input squared
    vo.squared = vo.input * vo.input;
  }
}


<|start_filename|>lib/src/patterns/facade/Facade.dart<|end_filename|>
part of puremvc;

/**
 * A base Multiton [IFacade] implementation.
 *
 * The Facade Pattern suggests providing a single
 * class to act as a central point of communication
 * for a subsystem.
 *
 * In PureMVC, the [IFacade] acts as an interface between
 * the core MVC actors [IModel], [IView], [IController], and
 * the rest of your application, which (aside from view components
 * and data objects) is mostly expressed with [ICommand]s,
 * [IMediator]s, and [IProxy]s.
 *
 * This means you don't need to communicate with the [IModel],
 * [IView], [IController] instances directly, you can just go through
 * the [IFacade]. And conveniently, [ICommand]s, [IMediator]s, and
 * [IProxy]s all have a built-in reference to their [IFacade] after
 * initialization, so they're all plugged in and ready to communicate
 * with each other.
 *
 * See [Model], [View], [Controller], [INotification], [ICommand], [IMediator], [IProxy]
 */
class Facade implements IFacade
{
  /**
   * Constructor.
   *
   * This [IFacade] implementation is a Multiton,  so you should not call the constructor directly,
   * but instead call the static [getInstance] method.
   *
   * -  Throws [MultitonErrorFacadeExists] if instance for this Multiton key has already been constructed.
   */
  Facade( String key )
  {
    if ( instanceMap[ key ] != null ) throw new MultitonErrorFacadeExists();
    initializeNotifier( key );
    instanceMap[ multitonKey ] = this;
    initializeFacade();
  }

  /**
   * Initialize the Multiton [Facade] instance.
   *
   * Called automatically by the constructor. Override in your
   * subclass to do any subclass specific initializations. Be
   * sure to call [super.initializeFacade()], though.
   */
  void initializeFacade(  )
  {
    initializeModel();
    initializeController();
    initializeView();
  }

  /**
   * [IFacade] Multiton Factory method
   *
   * -  Returns the [IFacade] Multiton instance for the specified key.
   */
  static IFacade getInstance( String key )
  {
    if ( key == null || key == "" ) return null;
    if ( instanceMap == null ) instanceMap = new Map<String,IFacade>();
    if ( instanceMap[ key ] == null ) instanceMap[ key ] = new Facade( key );
    return instanceMap[ key ];
  }

  /**
   * Initialize the [IController].
   *
   * Called by the [initializeFacade] method.
   *
   * Override this method in a subclass of [Facade] if you want to provide a different [IController].
   */
  void initializeController( )
  {
    if ( controller != null ) return;
    controller = Controller.getInstance( multitonKey );
  }

  /**
   * Initialize the [IModel].
   *
   * Called by the [initializeFacade] method.
   *
   * Override this method in a subclass of [Facade] if you wish to initialize a different [IModel].
   */
  void initializeModel( )
  {
    if ( model != null ) return;
    model = Model.getInstance( multitonKey );
  }


  /**
   * Initialize the [IView].
   *
   * Called by the [initializeFacade] method.
   *
   * Override this method in a subclass of [Facade] if you wish to initialize a different [IView].
   */
  void initializeView( )
  {
    if ( view != null ) return;
    view = View.getInstance( multitonKey );
  }

  /**
   * Register an [INotification] to [ICommand] mapping with the [Controller].
   *
   * -  Param [noteName] - the name of the [INotification] to associate the [ICommand] with.
   * -  Param [commandFactory] - a function that creates a new instance of the [ICommand].
   */
  void registerCommand( String noteName, Function commandFactory )
  {
    controller.registerCommand( noteName, commandFactory );
  }

  /**
   * Remove a previously registered [INotification] to [ICommand] mapping from the [IController].
   *
   * -  Param [noteName] - the name of the [INotification] to remove the [ICommand] mapping for
   */
  void removeCommand( String noteName )
  {
    controller.removeCommand( noteName );
  }

  /**
   * Check if an [ICommand] is registered for a given [INotification] name with the [IController].
   *
   * -  Param [noteName] - the name of the [INotification].
   * -  Returns [bool] - whether an [ICommand] is currently registered for the given [noteName].
   */
  bool hasCommand( String noteName )
  {
    return controller.hasCommand( noteName );
  }

  /**
   * Register an [IProxy] instance with the [IModel].
   *
   * -  Param [proxy] - an object reference to be held by the [IModel].
   */
  void registerProxy( IProxy proxy )
  {
    model.registerProxy( proxy );
  }

  /**
   * Retrieve an [IProxy] instance from the [IModel].
   *
   * -  Param [proxyName] - the name of the [IProxy] instance to retrieve.
   * -  Returns the [IProxy] instance previously registered with the given [proxyName].
   */
  IProxy retrieveProxy( String proxyName )
  {
    return model.retrieveProxy( proxyName );
  }

  /**
   * Remove an [IProxy] instance from the [IModel].
   *
   * -  Param [proxyName] - name of the [IProxy] instance to be removed.
   * -  Returns [IProxy] - the [IProxy] that was removed from the [IModel].
   */
  IProxy removeProxy( String proxyName )
  {
    IProxy proxy;
    if ( model != null ) proxy = model.removeProxy ( proxyName );
    return proxy;
  }

  /**
   * Check if an [IProxy] is registered with the [IModel].
   *
   * -  Param [proxyName] - the name of the [IProxy] instance you're looking for.
   * -  Returns [bool] - whether an [IProxy] is currently registered with the given [proxyName].
   */
  bool hasProxy( String proxyName )
  {
    return model.hasProxy( proxyName );
  }

  /**
   * Register an [IMediator] instance with the [IView].
   *
   * Registers the [IMediator] so that it can be retrieved by name,
   * and interrogates the [IMediator] for its [INotification] interests.
   *
   * If the [IMediator] returns a list of [INotification]
   * names to be notified about, an [Observer] is created encapsulating
   * the [IMediator] instance's [handleNotification] method
   * and registering it as an [IObserver] for all [INotification]s the
   * [IMediator] is interested in.
   *
   * -  Param [mediator] - a reference to the [IMediator] instance.
   */
  void registerMediator( IMediator mediator )
  {
    if ( view != null ) view.registerMediator( mediator );
  }

  /**
   * Retrieve an [IMediator] from the [IView].
   *
   * -  Param [mediatorName] - the name of the [IMediator] instance to retrieve.
   * -  Returns  [IMediator] - the [IMediator] instance previously registered in this core with the given [mediatorName].
   */
  IMediator retrieveMediator( String mediatorName )
  {
    return view.retrieveMediator( mediatorName );
  }

  /**
   * Remove an [IMediator] from the [IView].
   *
   * -  Param [mediatorName] - name of the [IMediator] instance to be removed.
   * -  Returns [IMediator] - the [IMediator] that was removed from this core's [IView].
   */
  IMediator removeMediator( String mediatorName )
  {
    IMediator mediator;
    if ( view != null ) mediator = view.removeMediator( mediatorName );
    return mediator;
  }

  /**
   * Check if a Mediator is registered or not
   *
   * Param [mediatorName]
   * Returns [bool] - whether an [IMediator] is registered in this core with the given [mediatorName].
   */
  bool hasMediator( String mediatorName )
  {
    return view.hasMediator( mediatorName );
  }

  /**
   * Send an [INotification].
   *
   * Convenience method to prevent having to construct new
   * [INotification] instances in our implementation code.
   *
   * -  Param [noteName] the name of the note to send
   * -  Param [body] - the body of the note (optional)
   * -  Param [type] - the type of the note (optional)
   */
  void sendNotification( String noteName, [dynamic body, String type] )
  {
    notifyObservers( new Notification( noteName, body, type ) );
  }

  /**
   * Register an [IObserver] to be notified of [INotification]s with a given name.
   *
   * -  Param [noteName] - the name of the [INotification] to notify this [IObserver] of.
   * -  Param [observer] - the [IObserver] to register.
   */
  void registerObserver( String noteName, IObserver observer )
  {
    view.registerObserver(noteName, observer);
  }

  /**
   * Remove an [IObserver] from the list for a given [INotification] name.
   *
   * -  Param [noteName] - which [IObserver] list to remove from.
   * -  Param [notifyContext] - remove [IObserver]s with this object as the [notifyContext].
   */
  void removeObserver( String noteName, Object notifyContext )
  {
    view.removeObserver( noteName, notifyContext );
  }

  /**
   * Notify [IObserver]s.
   *
   * This method allows you to send custom [INotification] classes using the [IFacade].
   *
   * Usually you should just call [sendNotification] and pass the parameters,
   * never having to construct an [INotification] yourself.
   *
   * -  Param [note] the [INotification] to have the [View] notify [Observers] of.
   */
  void notifyObservers( INotification note )
  {
    if ( view != null ) view.notifyObservers( note );
  }

  /**
   * Initialize this [INotifier].
   *
   * This is how an [INotifier] gets its [multitonKey].
   * Calls to [sendNotification] or to access the
   * [facade] will fail until after this method
   * has been called.
   *
   * -  Param [key] - the [multitonKey] for this [INotifier] to use.
   */
  void initializeNotifier( String key )
  {
    multitonKey = key;
  }

  /**
   * Check if a Core is registered or not.
   *
   * -  Param [key] - the Multiton key for the Core.
   * -  Returns [bool] - whether a Core is registered with the given [key].
   */
  static bool hasCore( String key )
  {
    return ( instanceMap[ key ] != null );
  }

  /**
   * Remove a Core.
   *
   * Remove the [IModel], [IView], [IController], and [IFacade]
   * instances for the given key.</P>
   *
   * -  Param [key] - the Multiton key of the Core to remove.
   */
  static void removeCore( String key )
  {
    if ( instanceMap[ key ] == null ) return;
    Model.removeModel( key );
    View.removeView( key );
    Controller.removeController( key );
    instanceMap[ key ] = null;
  }

  // References to [IModel], [IView], and [IController]
  IController controller;
  IModel model;
  IView view;

  // This [IFacade]'s Multiton key
  String multitonKey;

  // The [IFacade] Multiton instanceMap.
  static Map<String,IFacade> instanceMap;
}

class MultitonErrorFacadeExists {
  const MultitonErrorFacadeExists ();

  String toString() {
    return "IFacade Multiton instance already constructed for this key.";
  }
}



<|start_filename|>test/Unit_Tests.dart<|end_filename|>
// PureMVC Unit Test Library
library puremvc_unit_tests;

// DART HTML Library
import 'dart:html';

// The Unit Testing Framework for Dart
import 'package:unittest/unittest.dart';
import 'package:unittest/html_enhanced_config.dart';

// PureMVC Framework for Dart
import 'package:puremvc/puremvc.dart' as mvc;

// PureMVC Unit Tests
part 'Test_Notification.dart';
part 'Test_Observer.dart';
part 'Test_SimpleCommand.dart';
part 'Test_MacroCommand.dart';
part 'Test_Proxy.dart';
part 'Test_Mediator.dart';
part 'Test_Model.dart';
part 'Test_View.dart';
part 'Test_Controller.dart';
part 'Test_Facade.dart';

class Unit_Tests
{
  Unit_Tests()
  {
   // unittestConfiguration = new Unit_Tests_Config();
   useHtmlEnhancedConfiguration();
  }

  void onTestResult( TestCase testCase ) {
    write( "${testCase.result}  ${testCase.currentGroup}" );

  }

  void write(String message) {
    document.querySelector('#status').innerHtml = message;
  }

  void run() {

    // Now, run the PureMVC Tests
    new Test_Notification().run();
    new Test_Observer().run();
    new Test_SimpleCommand().run();
    new Test_MacroCommand().run();
    new Test_Proxy().run();
    new Test_Mediator().run();
    new Test_Model().run();
    new Test_View().run();
    new Test_Controller().run();
    new Test_Facade().run();
  }
}


/**
 * Application entry point.
 */
void main()
{
  // Unit test program, reporting for duty!
  new Unit_Tests().run();
}

<|start_filename|>lib/src/core/Model.dart<|end_filename|>
part of puremvc;

/**
 * A PureMVC MultiCore [IModel] implementation.
 *
 * In PureMVC, [IModel] implementors provide
 * access to [IProxy] objects by named lookup.
 *
 * An [IModel] assumes these responsibilities:
 *
 * -  Maintain a cache of [IProxy] instances.
 * -  Provide methods for registering, retrieving, and removing [IProxy] instances.
 *
 * Your application must register [IProxy] instances
 * with the [IModel]. Typically, you use an
 * [ICommand] to create and register [IProxy]
 * instances once the [IFacade] has initialized the core
 * actors.
 *
 * See [IProxy], [IFacade]
 */
class Model implements IModel
{
  /**
   * Constructor.
   *
   * This [IModel] implementation is a Multiton, so you should not call the constructor directly,
   * but instead call the static [getInstance] method.
   *
   * -  Throws [MultitonErrorModelExists] if instance for this Multiton key instance has already been constructed.
   */
  Model( String key )
  {
    if ( instanceMap[ key ] != null ) throw new MultitonErrorModelExists();
    multitonKey = key;
    instanceMap[ multitonKey ] = this;
    proxyMap = new Map<String,IProxy>();
    initializeModel();
  }

  /**
   * Initialize the [IModel] instance.
   *
   * Called automatically by the constructor, this is your opportunity to initialize the Singleton
   * instance in your subclass without overriding the constructor.
   */
  void initializeModel(  ){ }

  /**
   * [IModel] Multiton Factory method.
   *
   * -  Returns the [IModel] Multiton instance for the specified key.
   */
  static IModel getInstance( String key )
  {
    if ( key == null || key == "" ) return null;
    if ( instanceMap == null ) instanceMap = new Map<String,IModel>();
    if ( instanceMap[ key ] == null ) instanceMap[ key ] = new Model( key );
    return instanceMap[ key ];
  }

  /**
   * Register an [IProxy] instance with the [IModel].
   *
   * -  Param [proxy] - an object reference to be held by the [IModel].
   */
  void registerProxy( IProxy proxy )
  {
    proxy.initializeNotifier( multitonKey );
    proxyMap[ proxy.getName() ] = proxy;
    proxy.onRegister();
  }

  /**
   * Retrieve an [IProxy] instance from the [IModel].
   *
   * -  Param [proxyName] - the name of the [IProxy] instance to retrieve.
   * -  Returns the [IProxy] instance previously registered with the given [proxyName].
   */
  IProxy retrieveProxy( String proxyName )
  {
    return proxyMap[ proxyName ];
  }

  /**
   * Remove an [IProxy] instance from the [IModel].
   *
   * -  Param [proxyName] - name of the [IProxy] instance to be removed.
   * -  Returns [IProxy] - the [IProxy] that was removed from the [IModel].
   */
  IProxy removeProxy( String proxyName )
  {
    IProxy proxy = proxyMap[ proxyName ];
    if ( proxy != null )
    {
      proxyMap[ proxyName ] = null;
      proxy.onRemove();
    }
    return proxy;
  }

  /**
   * Check if an [IProxy] is registered with the [IModel].
   *
   * -  Param [proxyName] - the name of the [IProxy] instance you're looking for.
   * -  Returns [bool] - whether an [IProxy] is currently registered with the given [proxyName].
   */
  bool hasProxy( String proxyName )
  {
    return proxyMap[ proxyName ] != null;
  }

  /**
   * Remove an [IModel] instance.
   *
   * -  Param [key] - the multitonKey of [IModel] instance to remove
   */
  static void removeModel( String key )
  {
    instanceMap[ key ] = null;
  }

  // Mapping of proxyNames to IProxy instances
  Map<String,IProxy> proxyMap;

  // Multiton instance map
  static Map<String,IModel> instanceMap;

  // The Multiton Key for this Core
  String multitonKey;
}

class MultitonErrorModelExists {
  const MultitonErrorModelExists();

  String toString() {
    return "IModel Multiton instance already constructed for this key.";
  }
}


<|start_filename|>test/Test_MacroCommand.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_MacroCommand
{
  _tests()
  {
    group('MacroCommand', ()
    {
      test('Constructor', () {
        // Create a MacroCommand
        mvc.ICommand macroCommand = new MacroCommandTestCommand();
        expect( macroCommand, isNotNull );
      });

      test('execute()', () {
        // Create a MacroCommand
        mvc.ICommand macroCommand = new MacroCommandTestCommand();

        // Create a VO and a Notification to pass it to the Command with
        MacroCommandTestVO vo = new MacroCommandTestVO( 5 );
        mvc.INotification note = new mvc.Notification( "MacroCommandTest", vo );

        // Execute the MacroCommand execute the note
        macroCommand.execute(note);
        expect( vo.doubled, equals(10) );
        expect( vo.squared, equals(25) );
      });

      test('initializeNotifier()', () {
        // Create a MacroCommand
        mvc.INotifier notifier = new MacroCommandTestCommand();

        // Call initializeNotifier()
        String multitonKey = "MacroCommandTest";
        notifier.initializeNotifier( multitonKey );

        // Make sure MacroCommand's multitonKey was set
        expect( notifier.multitonKey, isNotNull );
      });
    });
  }

  run() {
    _tests();
  }
}

class MacroCommandTestVO
{
  int input;
  int doubled;
  int squared;

  MacroCommandTestVO( int this.input ) {}
}

class MacroCommandTestCommand extends mvc.MacroCommand
{
  void initializeMacroCommand() {
    // Add the subcommands
    addSubCommand( () => new MacroCommandTestDoubleInputCommand() );
    addSubCommand( () => new MacroCommandTestSquareInputCommand() );
  }
}

class MacroCommandTestDoubleInputCommand extends mvc.SimpleCommand
{
  void execute( mvc.INotification note )
  {
    // Get the VO from the note body
    MacroCommandTestVO vo = note.getBody();

    // Compute the input doubled
    vo.doubled = vo.input * 2;
  }
}

class MacroCommandTestSquareInputCommand extends mvc.SimpleCommand
{
  void execute( mvc.INotification note )
  {
    // Get the VO from the note body
    MacroCommandTestVO vo = note.getBody();

    // Compute the input doubled
    vo.squared = vo.input * vo.input;
  }
}

<|start_filename|>test/Test_Proxy.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_Proxy
{
  _tests()
  {
    group('ProxyTest', ()
    {
      test('Constructor +name', () {
        String proxyName = "TestProxy1";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );
        expect( proxy, isNotNull );
      });

      test('getName(), .name', () {
        // Create a Proxy
        String proxyName = "TestProxy2";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );

        // Make sure the Proxy name was set
        expect( proxy.getName(), equals(proxyName) );
        expect( proxy.name, equals(proxyName) );
      });

      test('Constructor +data, getData(), .data', () {
        // Create some data
        List<String> data = ['red', 'green', 'blue'];

        // Create a Proxy with that data
        String proxyName = "TestProxy3";
        mvc.IProxy proxy = new mvc.Proxy( proxyName, data );

        // Make sure the Proxy was created
        expect( proxy, isNotNull );

        // Make sure the data was set
        expect( proxy.getData(), same(data) );
        expect( proxy.data, same(data) );
      });

      test('setData(), getData(), .data', () {
        // Create some data
        List<String> data = ['red', 'green', 'blue'];

        // Create a Proxy
        String proxyName = "TestProxy4";
        mvc.IProxy proxy = new mvc.Proxy( proxyName );

        // Call setData()
        proxy.setData( data );

        // Make sure the data was set
        expect( proxy.getData(), same(data) );
        expect( proxy.data, same(data) );

      });

      test('initializeNotifier()', () {
        // Create a Proxy
        String proxyName = "TestProxy5";
        mvc.INotifier notifier = new mvc.Proxy( proxyName );

        // Call initializeNotifier()
        String multitonKey = "ProxyTestKey";
        notifier.initializeNotifier( multitonKey );

        // Make sure the Proxy's multitonKey was set
        expect( notifier.multitonKey, isNotNull );
      });
    });
  }

  run() {
    _tests();
  }
}


<|start_filename|>lib/src/interfaces/INotification.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC MultiCore Notification.
 *
 * The Observer Pattern as implemented within PureMVC exists
 * to support publish/subscribe communication between actors.
 *
 * [INotification]s are not meant to be a replacement for [Event]s,
 * but rather an internal communication mechanism that ensures
 * PureMVC is portable regardless of what type of Event mechanism
 * is supported (or not) on a given platform.
 *
 * Generally, [IMediator] implementors place [Event] listeners on
 * their view components, and [IProxy] implementors place [Event]
 * listeners on service components. Those [Event]s are then handled in
 * the usual way, and may lead to the broadcast of [INotification]s
 * that trigger [ICommand]s or notify [IMediator]s.
 *
 * See [IView], [IObserver]
 */
abstract class INotification
{

    /**
     * Get the [name] of the [INotification].
     *
     * -  Returns [String] - the name of the [INotification].
     */
    String getName();

    /**
     * Set the [body] of the [INotification].
     *
     * -  Param [body] - the body of the [INotification].
     */
    void setBody( Object body );

    /**
     * Get the [body] of the [INotification].
     *
     * -  Returns [Dynamic] - the body of the [INotification].
     */
    dynamic getBody();

    /**
     * Set the [type] of the [INotification].
     *
     * -  Param [type] - the type of the [INotification].
     */
    void setType( String type );

    /**
     * Get the [type] of the [INotification].
     *
     * -  Returns [String] - the type of the [INotification].
     */
    String getType();

    /**
     * This [INotifications]'s [body]
     */
    void set body( dynamic bodyObject );
    dynamic get body;

    /**
     * This [INotifications]'s [name]
     */
    void set name( String noteName );
    String get name;

    /**
     * This [INotifications]'s [type]
     */
    void set type( String noteType );
    String get type;


}


<|start_filename|>test/Test_Mediator.dart<|end_filename|>
part of puremvc_unit_tests;

class Test_Mediator
{
  _tests()
  {
    group('Mediator', ()
    {
      test('Constructor', () {
        // Create a Mediator
        String mediatorName = "TestMediator1";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );

        // Make sure it was created
        expect( mediator, isNotNull );
      });

      test('getMediatorName()', () {
        // Create a Mediator
        String mediatorName = "TestMediator2";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );

        // Make sure the Mediator's name was set
        expect( mediator.getName(), equals(mediatorName) );
        expect( mediator.name, equals(mediatorName) );
      });

      test('Constructor +viewComponent, getViewComponent(), .viewComponent', () {
        // Create a view component
        Object viewComponent = new Object();

        // Create a Mediator with the view component
        String mediatorName = "TestMediator3";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName, viewComponent );

        // Make sure the view component was set
        expect( mediator.getViewComponent(), same(viewComponent) );
        expect( mediator.viewComponent, same(viewComponent) );
      });

      test('setViewComponent(), getViewComponent()', () {
        // Create a view component
        Object viewComponent = new Object();

        // Create a Mediator
        String mediatorName = "TestMediator4";
        mvc.IMediator mediator = new mvc.Mediator( mediatorName );

        // Call setViewComponent()
        mediator.setViewComponent( viewComponent );

        // Make sure the view component was set
        expect( mediator.getViewComponent(), same(viewComponent) );
        expect( mediator.viewComponent, same(viewComponent) );
      });

      test('initializeNotifier()', () {
        // Create a Mediator
        String mediatorName = "TestMediator5";
        mvc.INotifier notifier = new mvc.Mediator( mediatorName );

        // Call initializeNotifier()
        String multitonKey = "MediatorTestKey";
        notifier.initializeNotifier( multitonKey );

        // Make sure the Mediator's multitonKey was set
        expect( notifier.multitonKey, isNotNull );
      });
    });
  }

  run() {
    _tests();
  }
}


<|start_filename|>lib/src/interfaces/ICommand.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC MultiCore Command.
 *
 * See [IController], [INotification]
 */
abstract class ICommand extends INotifier
{
  /**
   * Execute the [ICommand]'s logic to handle a given [INotification].
   *
   * -  Param [note] - an [INotification] to handle.
   */
  void execute( INotification note );
}


<|start_filename|>lib/src/patterns/command/SimpleCommand.dart<|end_filename|>
part of puremvc;

/**
 * A base [ICommand] implementation for executing a block of business logic.
 *
 * Your subclass should override the [execute] method where your business logic will handle the [INotification].
 *
 * See [ICommand], [IController], [INotification], [MacroCommand], [INotifier]
 */
class SimpleCommand extends Notifier implements ICommand
{

  /**
   * Respond to the [INotification] that triggered this [SimpleCommand].
   *
   * Perform business logic e.g., complex validation, processing, model changes.
   *
   * -  Param [note] - an [INotification] object that triggered the execution of this [SimpleCommand]
   */
  void execute( INotification note ){ }

}

<|start_filename|>lib/src/patterns/command/MacroCommand.dart<|end_filename|>
part of puremvc;

/**
 * A base [ICommand] implementation that synchronously executes other [ICommand]s.
 *
 * An [MacroCommand] maintains an list of [ICommand] factories called 'SubCommands'.
 *
 * When [execute] is called, the [MacroCommand] instantiates and calls [execute] on each of its 'SubCommands' turn.
 * Each 'SubCommand' will be passed a reference to the original [INotification].
 *
 * Unlike [SimpleCommand], your subclass should not override [execute], but instead,
 * should override the [initializeMacroCommand] method, calling [addSubCommand] once for each 'SubCommand' to be executed.
 *
 * See [ICommand], [IController], [INotification], [SimpleCommand], [INotifier]
 */
class MacroCommand extends Notifier implements ICommand
{
  /**
   * Constructor.
   *
   * You should not need to define a constructor,
   * instead, override the [initializeMacroCommand]
   * method.
   */
  MacroCommand()
  {
    subCommands = new List<Function>();
    initializeMacroCommand();
  }

  /**
   * Initialize the [MacroCommand].
   *
   * In your subclass, override this method to initialize the [MacroCommand]'s 'SubCommand' list
   * with [ICommand] factories by calling [addSubCommand].
   *
   * Note that 'SubCommand's may be any [ICommand] implementor, [MacroCommand]s or [SimpleCommands] are both acceptable.
   */
  void initializeMacroCommand(){}

  /**
   * Add a 'SubCommand'.
   *
   * The 'SubCommand' will be called in First In/First Out (FIFO) order.
   *
   * -  Param [commandFactory] - a Function that constructs an instance of an [ICommand].
   */
  void addSubCommand( Function commandFactory )
  {
      subCommands.add( commandFactory );
  }

  /**
   * Execute this [MacroCommand]'s 'SubCommands'.
   *
   * The 'SubCommands' will be called in First In/First Out (FIFO) order.
   *
   * -  Param [note] - the [INotification] object to be passed to each 'SubCommand'.
   */
  void execute( INotification note )
  {
      for ( Function commandFactory in subCommands ) {
          ICommand commandInstance = commandFactory();
          commandInstance.initializeNotifier( multitonKey );
          commandInstance.execute( note );
      }
  }

  // This [MacroCommand]'s 'SubCommands'
  List<Function> subCommands;
}


<|start_filename|>lib/src/interfaces/IView.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC MultiCore View.
 *
 * In PureMVC, [IView] implementors assume these responsibilities:
 *
 * -  Maintain a cache of [IMediator] instances.
 * -  Provide methods for registering, retrieving, and removing [IMediator]s.
 * -  Managing the [IObserver] lists for each [INotification].
 * -  Providing a method for attaching [IObserver]s to an [INotification]'s [IObserver] list.
 * -  Providing a method for broadcasting an [INotification] to each of the [IObserver]s in a list.
 * -  Notifying the [IObservers] of a given [INotification] when it broadcast.
 *
 * See [IMediator], [IObserver], [INotification]
 */
abstract class IView
{
  /**
   * Register an [IObserver] to be notified of [INotification]s with a given name.
   *
   * -  Param [noteName] - the name of the [INotification] to notify this [IObserver] of.
   * -  Param [observer] - the [IObserver] to register.
   */
  void registerObserver( String noteName, IObserver observer);

  /**
   * Remove an [IObserver] from the list for a given [INotification] name.
   *
   * -  Param [noteName] - which [IObserver] list to remove from.
   * -  Param [notifyContext] - remove [IObserver]s with this object as the [notifyContext].
   */
  void removeObserver( String noteName, Object notifyContext );

  /**
   * Notify the [IObserver]s for a particular [INotification].
   *
   * All previously attached [IObserver]s for this [INotification]'s
   * list are notified and are passed a reference to the [INotification] in
   * the order in which they were registered.
   *
   * -  Param [note] - the [INotification] to notify [IObservers] of.
   */
  void notifyObservers( INotification note );

  /**
   * Register an [IMediator] instance with the [IView].
   *
   * Registers the [IMediator] so that it can be retrieved by name,
   * and interrogates the [IMediator] for its [INotification] interests.
   *
   * If the [IMediator] returns a list of [INotification]
   * names to be notified about, an [Observer] is created encapsulating
   * the [IMediator] instance's [handleNotification] method
   * and registering it as an [IObserver] for all [INotification]s the
   * [IMediator] is interested in.
   *
   * -  Param [mediator] - a reference to the [IMediator] instance.
   */
  void registerMediator( IMediator mediator );

  /**
   * Retrieve an [IMediator] from the [IView].
   *
   * -  Param [mediatorName] - the name of the [IMediator] instance to retrieve.
   * -  Returns [IMediator] - the [IMediator] instance previously registered in this core with the given [mediatorName].
   */
  IMediator retrieveMediator( String mediatorName );

  /**
   * Remove an [IMediator] from the [IView].
   *
   * -  Param [mediatorName] - name of the [IMediator] instance to be removed.
   * -  Returns [IMediator] - the [IMediator] that was removed from this core's [IView].
   */
  IMediator removeMediator( String mediatorName );

  /**
   * Check if an [IMediator] is registered with the [IView].
   *
   * -  Param [mediatorName] - the name of the [IMediator] you're looking for.
   * -  Returns [bool] - whether an [IMediator] is registered in this core with the given [mediatorName].
   */
  bool hasMediator( String mediatorName );

  /**
   * This [IView]'s Multiton key
   */
  void set multitonKey( String key );
  String get multitonKey;

}



<|start_filename|>example/Framework_Verify.dart<|end_filename|>
import 'dart:html';
import 'package:puremvc/puremvc.dart' as mvc;

class Framework_Verify {

  Framework_Verify() {
  }

  void verify()
  {
    String multitonKey = "Test Core";
    String dataPoint1 = "Hello";
    String dataPoint2 = "World";
    String proxyName = "DataProxy";
    List<String> retrievedObject;
    String badJuju = "";

    try {
      write ("<UL>");

      // Get a Facade
      mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );
      write ("<LI>Facade created for ${multitonKey}.");

      // Create some data
      List<String> dataObject = new List<String>();
      write ("<LI>Data Object (List&ltString&gt) created.</LI>");
      dataObject.add(dataPoint1);
      write ("<LI>Data point added '${dataPoint1}'.</LI>");
      dataObject.add(dataPoint2);
      write ("<LI>Data point added '${dataPoint2}'.</LI>");

      // Register a Proxy to hold the data
      mvc.IProxy proxy = new mvc.Proxy( proxyName, dataObject );
      write( "<LI>Proxy '${proxyName}' created with for Data Object.</LI>");
      facade.registerProxy( proxy );
      write ("<LI>Proxy '${proxyName}' registered with Model, via Facade.</LI>");

      // Now retrieve the Proxy
      mvc.IProxy retrievedProxy = facade.retrieveProxy( proxyName );
      write ("<LI>Proxy '${proxyName}' retrieved from Model, via Facade.</LI>");

      // And get the data
      retrievedObject = retrievedProxy.getData();
      write ("<LI>Data Object (List&ltString&gt) retrieved from ${proxyName}</LI>");
      write("<LI>Data Object (List&ltString&gt) Length: ${retrievedObject.length}</LI>" );
      write("<LI>Contents: ${retrievedObject[0]} ${retrievedObject[1]}</LI>");

      write ("</UL>");
      // Prove errors will be reported
      // throw "Fungers! I've got jelly in my ears!";

    } on Error catch ( e ) {
      // Catch any error
      badJuju = e.toString();

    } finally {
      // Report final status
      if ( badJuju.length == 0 && retrievedObject != null
           && retrievedObject[0] == dataPoint1
           && retrievedObject[1] == dataPoint2 ){
        write( "<P/><B>Science!</B> PureMVC is purring like a kitten. Take her out for a spin!");
      } else {
        write( "<P/><B>Claptrap!</B> Someone's thrown a spanner in the works.");
        if( badJuju.length>0 ) write( "<B>Bad juju reported:</B> ${badJuju}");
      }
    }

  }

  void write(String message) {
    // the HTML library defines a global "document" variable
    document.querySelector('#text').innerHtml = "${document.querySelector('#text').innerHtml}${message}";
  }
}

void main() {
  new Framework_Verify().verify();
}


<|start_filename|>lib/src/interfaces/IObserver.dart<|end_filename|>
part of puremvc;

/**
 * The interface definition for a PureMVC MultiCore Observer.
 *
 * In PureMVC, [IObserver] implementors assume these responsibilities:
 *
 * -  Encapsulate the notification (callback) method of the interested object.
 * -  Encapsulate the notification context (this) of the interested object.
 * -  Provide methods for setting the interested object's notification method and context.
 * -  Provide a method for notifying the interested object.
 *
 * The Observer Pattern as implemented within PureMVC exists
 * to support publish/subscribe communication between actors.
 *
 * An [IObserver] is an object that encapsulates information
 * about an interested object with a notification (callback)
 * method that should be called when an [INotification] is
 * broadcast. The [IObserver] then acts as a conduit for
 * notifying the interested object.
 *
 * [IObserver]s can receive [Notification]s by having their
 * [notifyObserver] method invoked, passing in an object
 * implementing the [INotification] interface.
 *
 * See [IView], [INotification]
 */
abstract class IObserver
{
    /**
     * Set the notification method.
     *
     * The notification method should take one parameter of type [INotification].
     *
     * -  Param [notifyMethod] - the notification (callback) method of the interested object.
     */
    void setNotifyMethod( Function callback );

    /**
     * Set the notification context.
     *
     * -  Param [caller] - a reference to the object to be notified.
     */
    void setNotifyContext( Object caller );

    /**
     * Get the notification method.
     *
     * -  Returns [Function] - the notification (callback) method of the interested object.
     */
    Function getNotifyMethod();

    /**
     * Get the notification context.
     *
     * -  Returns [Object] - the caller.
     */
    Object getNotifyContext();

    /**
     * Compare a given object to the [notifyContext] (caller) object.
     *
     * -  Param [Object] - the object to compare.
     * -  Returns [bool] - whether the given object and the [notifyContext] (caller) are the same.
     */
    bool compareNotifyContext( Object object );

    /**
     * Notify the interested object.
     *
     * -  Param [note] - the [INotification] to pass to the caller's [notifyMethod].
     */
    void notifyObserver( INotification note );

    /**
     * This [IObserver]'s [notifyMethod] (i.e., callback)
     */
    void set notifyMethod( Function callback );
    Function get notifyMethod;

    /**
     * This [IObserver]'s [notifyContext] (i.e., caller)
     */
    void set notifyContext( Object caller );
    Object get notifyContext;

}

