Related Posts
Abstract Commands
Basic Cairngorm Commands
In the base implementation of the Cairngorm micro-architecture, events and commands are mapped on a 1-1 basis. For every invoker (event) you have to specify one command in your controller.
public function Controller()
{
super();
addCommand(TeammateEvent.LOAD_TEAMMATES, LoadTeammatesCommand);
addCommand(EffortEvent.LOAD_TYPES, LoadEffortTypesCommand);
addCommand(ProjectEvent.LOAD_PROJECTS, LoadProjectsCommand);
addCommand(TeammateEvent.LOAD_TEAMMATE_ROLES, LoadTeammateRolesCommand);
...
}
For most cases, this is perfectly fine, but in a data-heavy model, such as the one being built for my current application, I need to initialize the application and fire off many individual events in order to load my model with base data.
// Load all teammates in the database for display in the reports tab
new TeammateEvent(TeammateEvent.LOAD_TEAMMATES).dispatch();
// Load all effort types
new EffortEvent(EffortEvent.LOAD_TYPES).dispatch();
// Load all projects
new ProjectEvent(ProjectEvent.LOAD_PROJECTS).dispatch();
// Load all roles
new TeammateEvent(TeammateEvent.LOAD_TEAMMATE_ROLES).dispatch();
...
Batch Commands
In order to avoid having to dispatch n events for n commands to be executed, I would rather map 1 event to n commands and have them fired off in sequence. Then, if I need a batch of commands to fire, I only need to dispatch one event, instead of the 4 I used in the example above.
new ApplicationEvent(ApplicationEvent.LOAD_MODEL).dispatch();
Unfortunately, Cairngorm does not allow this, so I had to extend the basic architecture. I created a addCommands() function that maps a single event to multiple commands as an array.
public class Controller extends ExtendedFrontController
{
public function Controller()
{
addCommands(ApplicationEvent.LOAD_MODEL, [LoadTeammatesCommand,
LoadEffortTypesCommand,
LoadProjectsCommand,
LoadTeammateRolesCommand,
...]);
}
}
Extended Controller Class
Here’s the code that I’ve come up with so far. This is working fine, but there still some things I plan on implementing in the future.
ExtendedFrontController.as
public class ExtendedFrontController extends FrontController
{
public function ExtendedFrontController()
{
super();
}
public function addCommands(commandName:String, commandRefs:Array, useWeakReference:Boolean = true):void
{
if(commands[ commandName ] != null)
{
throw new CairngormError( CairngormMessageCodes.COMMAND_ALREADY_REGISTERED, commandName );
}
if (commandRefs == null)
{
throw new Error("The commandRefs argument to addCommands() is null");
}
commands[commandName] = commandRefs;
for (var priority:uint = 0; priority < commandRefs.length; priority++)
{
CairngormEventDispatcher.getInstance().addEventListener(commandName, executeCommands, false, priority, useWeakReference);
}
}
protected function executeCommands(event:AbstractEvent):void
{
var commandsToInitialise:Array = getCommands(event.type);
var commandRef:Class;
for (var i:uint = 0; i < commandsToInitialise.length; i++)
{
commandRef = commandsToInitialise[i];
var commandToExecute:ICustomCommand = new commandRef();
commandToExecute.execute(event);
}
}
protected function getCommands(commandName:String):Array
{
var commands:Array = commands[commandName];
if ( commands == null )
throw new CairngormError( CairngormMessageCodes.COMMAND_NOT_FOUND, commandName );
return commands;
}
}