I wanted to be able to create a userPreference package, a product package, and order package, etc that I could then easily merge together into the main app.
so this is what I want.
package examples.cairngorm
{
import com.squaredi.frameworks.cairngorm.FrontControllerPlugin;
public class MainFC extends FrontControllerPlugin
{
public function MainFC()
{
super("main");
addController(new PlugInFC());
}
}
}
package examples.cairngorm
{
import com.squaredi.frameworks.cairngorm.FrontControllerPlugin;
public class PlugInFC extends FrontControllerPlugin
{
public function PlugInFC(id:String=null)
{
super("plugin");
addCommand(MyCoolThingEvent.EVENT, MyCoolThingCommand);
}
}
}
So here is the class that I created to do that.
FrontControllerPlugIn.as
package com.squaredi.frameworks.cairngorm
{
import com.adobe.cairngorm.CairngormError;
import com.adobe.cairngorm.CairngormMessageCodes;
import com.adobe.cairngorm.commands.ICommand;
import com.adobe.cairngorm.control.CairngormEvent;
import com.adobe.cairngorm.control.CairngormEventDispatcher;
import com.adobe.cairngorm.control.FrontController;
import flash.events.EventDispatcher;
import flash.utils.Dictionary;
import mx.logging.ILogger;
import mx.logging.Log;
import mx.utils.ObjectUtil;
/**
* This file is not likely to be edited. Please extend it for the various projects
*
* It also has the ability to add other Controllers into itself to make a plugin type architecture via the addController method
*
* As a plugin type architecture, there are use cases when a developer of a subcomponent or subproject might have a default implementation for and event
* (like show an alert for isolation testing), and know that the real implementation needs to be different.
*
* They should add the command via the addCommandToOverride method
*
* */
public class FrontControllerPlugin extends FrontController
{
protected static var logger:ILogger = Log.getLogger("com.squaredi.frameworks.cairngorm.FrontControllerPlugin")
private var pluginControllers:Array /*FrontControllerPlugin*/ = new Array();
private var cmdToPluginMap:Dictionary = new Dictionary(true);
protected var overrideCommands:Dictionary = new Dictionary(true);
private var id:String
public function FrontControllerPlugin(id:String = null)
{
super();
this.id = id;
if (Log.isInfo())
{
logger.info("FrontControllerPlugin constructor: " + this.toString());
}
}
/**
* Adds all of the event command pairs already assocated with another frontController
* This will throw an error if there are duplicated event names.
* The expection to this is that if the duplicated event name is intended to be override
*
* @param p
*
*/
public function addController(p:FrontControllerPlugin):void
{
/*
1) Recurse through all subcontrollers
2) Add only new controllers
3) Registger commands and deregister from added controllers
*/
//Do subcontrollers
if (p.pluginControllers.length >0)
{
//Register sub controllers first
var len:int = pluginControllers.length;
for (var i:int = 0; i < len; i++)
{
addController(p.pluginControllers[i]);
}
}
//Find new Controllers
if (findPlugin(p) < 0)
{
//Have not registered the controller yet
pluginControllers.push(p);
//Copy Override Items
for (var clz:String in p.overrideCommands)
{
overrideCommands[clz] = p.overrideCommands[clz];
}
//Copy the commands in and remove them from the plugin
var localcommands:Dictionary = p.commands;
for (var cmd:String in localcommands)
{
//Make sure not to add commands twice either
cmdToPluginMap[cmd] = p //Make sure to map the command before it gets added
addCommand(cmd,localcommands[cmd],true);
p.removeCommand(cmd);
}
}
else
{
if (Log.isInfo()){logger.info(p.toString() + " has already been added");}
}
}
protected function findPlugin(p:FrontControllerPlugin):int
{
var rtn:int = -1;
var len:int = pluginControllers.length;
for (var i:int = 0; i < len; i++)
{
if (pluginControllers[i].toString() == p.toString())
{
rtn = i;
break;
}
}
return rtn;
}
/**
*
* Overrides the super class to allow for an error message that includes which plugin the conflict already exists in
*
* @param commandName
* @param commandRef
* @param useWeakReference
*
*/
public override function addCommand(commandName:String, commandRef:Class, useWeakReference:Boolean=true):void
{
//Add usefull infomation for the alert
var pluginRef:FrontControllerPlugin = cmdToPluginMap[commandName];
var pluginName:String = this.toString();
if (pluginRef != null) {
pluginName = pluginRef.toString();
cmdToPluginMap[commandName] = this;
}
var commandReference:Class = commands[ commandName ]
if( commandReference != null)
{
//Verify that the command is not in the override list
var overrideCommandReference:Class = overrideCommands[ commandName ]
if (overrideCommandReference == null)
{
throw new Error( "Command already registered for " + commandName +" in " + pluginName);
}
else
{
//We are indeed overriding a command
if (Log.isInfo()) { logger.info(this.toString + " overriding a command")};
//lets remove the old reference and add the new
overrideCommands[ commandName ] = null;
delete overrideCommands[ commandName ];
cmdToPluginMap[commandName] = this;
}
}
commands[ commandName ] = commandRef;
CairngormEventDispatcher.getInstance().addEventListener( commandName, executeCommand, false, 0, useWeakReference );
}
/**
* * As a plugin type architecture, there are use cases when a developer of a subcomponent or subproject might have a default implementation for and event
* (like show an alert for isolation testing), and know that the real implementation needs to be different.
*
* Adding command via this method will throw an error if this frontController gets added to another one AND the command is not redefined in the new one
*
* */
public function addCommandToOverride(commandName:String, commandRef:Class, useWeakReference:Boolean=true):void
{
var commandReference:Class = overrideCommands[ commandName ]
if( commandReference != null)
{
var pluginRef:FrontControllerPlugin = cmdToPluginMap[commandName];
var pluginName:String = this.toString();
if (pluginRef != null) {
pluginName = pluginRef.toString();
cmdToPluginMap[commandName] = this;
}
throw new Error( "Command already registered for override " + commandName +" in " + pluginName);
}
overrideCommands[ commandName ] = commandRef;
addCommand(commandName, commandRef, useWeakReference);
}
protected function checkForOverrideCommands():void
{
//Copy Override Items
var needsToBeOverridden:Array = new Array();
for (var clz:String in overrideCommands)
{
needsToBeOverridden.push(clz);
}
if (needsToBeOverridden.length >0)
{
throw new Error (this.toString() + " needs to override the following events: " + needsToBeOverridden.toString());
}
}
internal function forceCheckForOverrideCommands():void
{
checkForOverrideCommands();
}
/**
*
* Creates the command and temporarily adds it to the context so that we get dependancy injection
*
*
*/
override protected function executeCommand( event : CairngormEvent ) : void
{
var commandToInitialise : Class = getCommand( event.type );
var commandToExecute : ICommand = new commandToInitialise();
if (Log.isInfo()) {logger.info("EVENT:" + event.type);}
commandToExecute.execute( event );
}
internal function getCommandForTesting(commandName:String):Class
{
try
{
var cmd:Class = getCommand(commandName)
}
catch (e:Error)
{
//Ignore Cairngorm Errors for testing
}
return cmd;
}
/**
*
* Returns the className for debugging purposes
*
* @return
*
*/
public function toString():String
{
var classInfo:Object = ObjectUtil.getClassInfo(this);
return classInfo.name + " (" + id + ")"
}
}
}
No comments:
Post a Comment