Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save abeldebeer/743573 to your computer and use it in GitHub Desktop.
Save abeldebeer/743573 to your computer and use it in GitHub Desktop.
AS3Signals implementation of @stray_and_ruby's GuardedCommandMap (first, untested version)
package org.robotlegs.core
{
import org.osflash.signals.ISignal;
/**
* @author Abel de Beer
*/
public interface IGuardedSignalCommandMap
{
function mapGuardedSignal(signal:ISignal, commandClass:Class, guards:*, oneShot:Boolean = false):void;
function mapGuardedSignalClass(signalClass:Class, commandClass:Class, guards:*, oneShot:Boolean = false):ISignal;
}
}
package org.robotlegs.base
{
import org.osflash.signals.ISignal;
import org.robotlegs.core.IGuardedSignalCommandMap;
import org.robotlegs.core.IInjector;
import flash.utils.Dictionary;
import flash.utils.describeType;
/**
* @author Abel de Beer
*/
public class GuardedSignalCommandMap extends SignalCommandMap implements IGuardedSignalCommandMap
{
protected var verifiedGuardClasses:Dictionary;
public static const E_GUARD_NOIMPL:String = "Guard Class does not implement an approve() method.";
public function GuardedSignalCommandMap(injector:IInjector)
{
super(injector);
verifiedGuardClasses = new Dictionary(false);
}
public function mapGuardedSignal(signal:ISignal, commandClass:Class, guards:*, oneShot:Boolean = false):void
{
verifyCommandClass(commandClass);
if (hasSignalCommand(signal, commandClass))
return;
if(!(guards is Array))
{
guards = [guards];
}
verifyGuardClasses(guards);
var signalCommandMap:Dictionary = signalMap[signal] ||= new Dictionary(false);
var callback:Function = function(a:* = null, b:* = null, c:* = null, d:* = null, e:* = null, f:* = null, g:* = null):void
{
routeSignalToGuardedCommand(signal, arguments, commandClass, oneShot, guards);
};
signalCommandMap[commandClass] = callback;
signal.add(callback);
}
public function mapGuardedSignalClass(signalClass:Class, commandClass:Class, guards:*, oneShot:Boolean = false):ISignal
{
var signal:ISignal = getSignalClassInstance(signalClass);
mapGuardedSignal(signal, commandClass, guards, oneShot);
return signal;
}
private function getSignalClassInstance(signalClass:Class):ISignal
{
return ISignal(signalClassMap[signalClass]) || createSignalClassInstance(signalClass);
}
private function createSignalClassInstance(signalClass:Class):ISignal
{
var injectorForSignalInstance:IInjector = injector;
var signal:ISignal;
if(injector.hasMapping(IInjector))
injectorForSignalInstance = injector.getInstance(IInjector);
signal = injectorForSignalInstance.instantiate(signalClass);
injectorForSignalInstance.mapValue(signalClass, signal);
signalClassMap[signalClass] = signal;
return signal;
}
protected function routeSignalToGuardedCommand(signal:ISignal, valueObjects:Array, commandClass:Class, oneshot:Boolean, guardClasses:Array):void
{
mapSignalValueClasses(signal.valueClasses, valueObjects);
for each (var guardClass:Class in guardClasses)
{
var nextGuard:Object = injector.instantiate(guardClass);
if (nextGuard.approve() == false)
{
unmapSignalValueClasses(signal.valueClasses);
return;
}
}
injector.instantiate(commandClass).execute();
if (oneshot)
unmapSignal(signal, commandClass);
}
private function mapSignalValueClasses(valueClasses:Array, valueObjects:Array):void
{
for (var i:int = 0; i < valueClasses.length; i++)
{
injector.mapValue(valueClasses[i], valueObjects[i]);
}
}
private function unmapSignalValueClasses(valueClasses:Array):void
{
for (var i:int = 0; i < valueClasses.length; i++)
{
injector.unmap(valueClasses[i]);
}
}
protected function verifyGuardClasses(guardClasses:Array):void
{
for each (var guardClass:Class in guardClasses)
{
if (!verifiedGuardClasses[guardClass])
{
verifiedGuardClasses[guardClass] = describeType(guardClass).factory.method.(@name == "approve").length();
if (!verifiedGuardClasses[guardClass])
throw new ContextError(E_GUARD_NOIMPL + ' - ' + guardClass);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment