/*
PureMVC Java port by Frederic Saunier <frederic.saunier@puremvc.org>
Adapted from sources of thoses different authors :
Donald Stinchfield <donald.stinchfield@puremvc.org>, et all
Ima OpenSource <opensource@ima.eu>
Anthony Quinault <anthony.quinault@puremvc.org>
PureMVC - Copyright(c) 2006-10 Futurescale, Inc., Some rights reserved.
Your reuse is governed by the Creative Commons Attribution 3.0 License
*/
package org.puremvc.java.interfaces;
/**
* The interface definition for a PureMVC Controller.
*
* <P>
* In PureMVC, an <code>IController</code> implementor follows the 'Command
* and Controller' strategy, and assumes these responsibilities:
* <UL>
* <LI> Remembering which <code>ICommand</code>s are intended to handle which
* <code>INotifications</code>.</LI>
* <LI> Registering itself as an <code>IObserver</code> with the
* <code>View</code> for each <code>INotification</code> that it has an
* <code>ICommand</code> mapping for.</LI>
* <LI> Creating a new instance of the proper <code>ICommand</code> to handle
* a given <code>INotification</code> when notified by the <code>View</code>.</LI>
* <LI> Calling the <code>ICommand</code>'s <code>execute</code> method,
* passing in the <code>INotification</code>.</LI>
* </UL>
*
* @see org.puremvc.java.interfaces INotification
* @see org.puremvc.java.interfaces ICommand
*/
public interface IController
{
/**
* Register a particular <code>ICommand</code> class as the handler for a
* particular <code>INotification</code>.
*
* @param notificationName
* the name of the <code>INotification</code>
* @param command
* the Class of the <code>ICommand</code>
*/
public void registerCommand( String notificationName, ICommand command );
/**
* Execute the <code>ICommand</code> previously registered as the handler
* for <code>INotification</code>s with the given notification name.
*
* @param notification
* the <code>INotification</code> to execute the associated
* <code>ICommand</code> for
*/
public void executeCommand( INotification notification );
/**
* Remove a previously registered <code>ICommand</code> to
* <code>INotification</code> mapping.
*
* @param notificationName
* the name of the <code>INotification</code> to remove the
* <code>ICommand</code> mapping for
*/
public void removeCommand( String notificationName );
/**
* Check if a Command is registered for a given Notification
*
* @param notificationName
* @return whether a Command is currently registered for the given <code>notificationName</code>.
*/
public boolean hasCommand( String notificationName);
}
/*
PureMVC Java port by Frederic Saunier <frederic.saunier@puremvc.org>
Adapted from sources of thoses different authors :
Donald Stinchfield <donald.stinchfield@puremvc.org>, et all
Ima OpenSource <opensource@ima.eu>
Anthony Quinault <anthony.quinault@puremvc.org>
PureMVC - Copyright(c) 2006-10 Futurescale, Inc., Some rights reserved.
Your reuse is governed by the Creative Commons Attribution 3.0 License
*/
package org.puremvc.java.core;
import java.util.HashMap;
import java.util.Map;
import org.puremvc.java.interfaces.ICommand;
import org.puremvc.java.interfaces.IController;
import org.puremvc.java.interfaces.IFunction;
import org.puremvc.java.interfaces.INotification;
import org.puremvc.java.patterns.observer.Observer;
/**
* A Singleton <code>IController</code> implementation.
*
* <P>
* In PureMVC, the <code>Controller</code> class follows the
* 'Command and Controller' strategy, and assumes these
* responsibilities:
* <UL>
* <LI> Remembering which <code>ICommand</code>s
* are intended to handle which <code>INotifications</code>.</LI>
* <LI> Registering itself as an <code>IObserver</code> with
* the <code>View</code> for each <code>INotification</code>
* that it has an <code>ICommand</code> mapping for.</LI>
* <LI> Creating a new instance of the proper <code>ICommand</code>
* to handle a given <code>INotification</code> when notified by the <code>View</code>.</LI>
* <LI> Calling the <code>ICommand</code>'s <code>execute</code>
* method, passing in the <code>INotification</code>.</LI>
* </UL>
*
* <P>
* Your application must register <code>ICommands</code> with the
* Controller.
* <P>
* The simplest way is to subclass </code>Facade</code>,
* and use its <code>initializeController</code> method to add your
* registrations.
*
* @see org.puremvc.java.core.View View
* @see org.puremvc.java.patterns.observer.Observer Observer
* @see org.puremvc.java.patterns.observer.Notification Notification
* @see org.puremvc.java.patterns.command.SimpleCommand SimpleCommand
* @see org.puremvc.java.patterns.command.MacroCommand MacroCommand
*/
public class Controller implements IController
{
/**
* Reference to the singleton instance
*/
protected static Controller instance;
/**
* Mapping of Notification names to Command Class references
*/
protected Map<String,ICommand> commandMap;
/**
* Local reference to View
*/
protected View view;
/**
* Constructor.
*
* <P>
* This <code>IController</code> implementation is a Singleton, so you
* should not call the constructor directly, but instead call the static
* Singleton Factory method <code>Controller.getInstance()</code>
*
*/
protected Controller()
{
instance = this;
commandMap = new HashMap<String,ICommand>();
initializeController();
}
/**
* Initialize the Singleton <code>Controller</code> instance.
*
* <P>Called automatically by the constructor.</P>
*
* <P>Note that if you are using a subclass of <code>View</code>
* in your application, you should <i>also</i> subclass <code>Controller</code>
* and override the <code>initializeController</code> method in the
* following way:</P>
*
* <listing>
* // ensure that the Controller is talking to my IView implementation
* override public function initializeController( ) : void
* {
* view = MyView.getInstance();
* }
* </listing>
*/
protected void initializeController( )
{
view = View.getInstance();
}
/**
* <code>Controller</code> Singleton Factory method.
*
* @return the Singleton instance of <code>Controller</code>
*/
public synchronized static Controller getInstance()
{
if (instance == null)
instance = new Controller();
return instance;
}
/**
* If an <code>ICommand</code> has previously been registered to handle a
* the given <code>INotification</code>, then it is executed.
*
* @param note
* The notification to send associated with the command to call.
*/
public void executeCommand( INotification note )
{
//No reflexion in GWT
//ICommand commandInstance = (ICommand) commandClassRef.newInstance();
ICommand commandInstance = (ICommand) this.commandMap.get( note.getName() );
if(commandInstance!=null){
commandInstance.execute( note );
}
}
/**
* Register a particular <code>ICommand</code> class as the handler for a
* particular <code>INotification</code>.
*
* <P>
* If an <code>ICommand</code> has already been registered to handle
* <code>INotification</code>s with this name, it is no longer used, the
* new <code>ICommand</code> is used instead.
* </P>
*
* The Observer for the new ICommand is only created if this the
* first time an ICommand has been regisered for this Notification name.
*
* @param notificationName
* the name of the <code>INotification</code>
* @param command
* an instance of <code>ICommand</code>
*/
public void registerCommand( String notificationName, ICommand command )
{
if( null != this.commandMap.put( notificationName, command ) )
return;
view.registerObserver
(
notificationName,
new Observer
(
new IFunction()
{
public void onNotification( INotification notification )
{
executeCommand( notification );
}
},
this
)
);
}
/**
* Remove a previously registered <code>ICommand</code> to
* <code>INotification</code> mapping.
*
* @param notificationName
* the name of the <code>INotification</code> to remove the
* <code>ICommand</code> mapping for
*/
public void removeCommand( String notificationName )
{
// if the Command is registered...
if ( hasCommand( notificationName ) )
{
// remove the observer
view.removeObserver( notificationName, this );
commandMap.remove( notificationName );
}
}
/**
* Check if a Command is registered for a given Notification
*
* @param notificationName
* The name of the command to check for existance.
*
* @return whether a Command is currently registered for the given <code>notificationName</code>.
*/
public boolean hasCommand(String notificationName )
{
return commandMap.containsKey(notificationName);
}
}