Skip to content

Commit

Permalink
first sketch for convenience command center
Browse files Browse the repository at this point in the history
  • Loading branch information
creynders committed Apr 9, 2013
1 parent fb22f9a commit 13df873
Show file tree
Hide file tree
Showing 9 changed files with 611 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//------------------------------------------------------------------------------
// Copyright (c) 2012 the original author or authors. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//------------------------------------------------------------------------------

package robotlegs.bender.extensions.commandCenter
{
import robotlegs.bender.extensions.commandCenter.api.ICommandCenter;
import robotlegs.bender.extensions.commandCenter.impl.CommandCenter;
import robotlegs.bender.extensions.utils.ensureContextUninitialized;
import robotlegs.bender.framework.api.IContext;
import robotlegs.bender.framework.api.IExtension;

/**
* A low level extension that provides common command mapping functionality
* for use in concrete command mapping extensions
*/
public class CommandCenterExtension implements IExtension
{

/*============================================================================*/
/* Public Functions */
/*============================================================================*/

/**
* @inheritDoc
*/
public function extend(context:IContext):void
{
ensureContextUninitialized(context, this);
context.injector.map(ICommandCenter).toSingleton(CommandCenter);
// TODO: Investigate SwiftSuspenders circular dependency handling
// Place a [PostConstruct] tag above the logger setter
// in CommandCenter to see what I mean
context.whenInitializing(function():void {
const commandCenter:CommandCenter = context.injector.getInstance(ICommandCenter);
commandCenter.logger = context.getLogger(commandCenter);
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//------------------------------------------------------------------------------
// Copyright (c) 2009-2013 the original author or authors. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//------------------------------------------------------------------------------

package robotlegs.bender.extensions.commandCenter.api
{
import robotlegs.bender.extensions.commandCenter.dsl.IOnceCommandConfig;
import robotlegs.bender.extensions.commandCenter.impl.CommandPayload;

public interface ICommandCenter
{
function configureCommand(commandClass:Class):IOnceCommandConfig;

function executeCommand(commandClassOrConfig:*, payload:CommandPayload = null):ICommandMapping;

function executeCommands(commandClassesOrConfigs:Array, payload:CommandPayload = null):Vector.<ICommandMapping>;

function detain(command:Object):void;

function release(command:Object):void;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package robotlegs.bender.extensions.commandCenter.dsl
{
import robotlegs.bender.extensions.commandCenter.impl.CommandPayload;

/**
* @author creynder
*/
public interface IOnceCommandConfig{
/**
* The "execute" method to invoke on the Command instance
* @param name Method name
* @return Self
*/
function withExecuteMethod(name:String):IOnceCommandConfig;

/**
* Guards to check before allowing a command to execute
* @param guards Guards
* @return Self
*/
function withGuards(... guards):IOnceCommandConfig;

/**
* Hooks to run before command execution
* @param hooks Hooks
* @return Self
*/
function withHooks(... hooks):IOnceCommandConfig;

/**
* Should the payload values be injected into the command instance?
* @param value Toggle
* @return Self
*/
function withPayloadInjection(value:Boolean = true):IOnceCommandConfig;
}
}
135 changes: 135 additions & 0 deletions src/robotlegs/bender/extensions/commandCenter/impl/CommandCenter.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//------------------------------------------------------------------------------
// Copyright (c) 2009-2013 the original author or authors. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//------------------------------------------------------------------------------

package robotlegs.bender.extensions.commandCenter.impl
{
import org.swiftsuspenders.Injector;
import robotlegs.bender.extensions.commandCenter.api.ICommandCenter;
import robotlegs.bender.extensions.commandCenter.api.ICommandExecutor;
import robotlegs.bender.extensions.commandCenter.api.ICommandMapping;
import robotlegs.bender.extensions.commandCenter.api.ICommandMappingList;
import robotlegs.bender.extensions.commandCenter.dsl.ICommandConfigurator;
import robotlegs.bender.extensions.commandCenter.dsl.IOnceCommandConfig;
import robotlegs.bender.framework.api.IContext;
import robotlegs.bender.framework.api.ILogger;

public class CommandCenter implements ICommandCenter
{

/*============================================================================*/
/* Public Properties */
/*============================================================================*/

private var _logger:ILogger;

public function set logger(value:ILogger):void
{
_logger = value;
}

/*============================================================================*/
/* Private Properties */
/*============================================================================*/

private var _context:IContext;

/*============================================================================*/
/* Constructor */
/*============================================================================*/

/**
* @private
*/
public function CommandCenter(context:IContext)
{
_context = context;
}

/*============================================================================*/
/* Public Functions */
/*============================================================================*/

/**
* @inheritDoc
*/
public function configureCommand(commandClass:Class):IOnceCommandConfig
{
return new OnceCommandConfig(commandClass);
}

/**
* @inheritDoc
*/
public function executeCommand(commandClassOrConfig:*, payload:CommandPayload = null):ICommandMapping
{
var executed:ICommandMapping;
const mapping:ICommandMapping = parseMappingFromClassOrConfig(commandClassOrConfig);
const callback:Function = function(mapping:ICommandMapping):void {
executed = mapping;
}
const executor:ICommandExecutor = new CommandExecutor(_context.injector.createChildInjector(), callback);
executor.execute(Vector.<ICommandMapping>([mapping]), payload);
return executed;
}

/**
* @inheritDoc
*/
public function executeCommands(commandClassesOrConfigs:Array, payload:CommandPayload = null):Vector.<ICommandMapping>
{
const numCommands:uint = commandClassesOrConfigs.length;
const list:Vector.<ICommandMapping> = new Vector.<ICommandMapping>(numCommands); //creates fixed length Vector [!]
for (var i:int = 0; i < numCommands; i++)
{
var mapping:ICommandMapping = parseMappingFromClassOrConfig(commandClassesOrConfigs[i]);
mapping && (list[i] = mapping); //no pushing, fixed length [!]
}
const executed:Vector.<ICommandMapping> = new Vector.<ICommandMapping>();
const callback:Function = function(mapping:ICommandMapping):void {
executed.push(mapping);
}
const executor:ICommandExecutor = new CommandExecutor(_context.injector.createChildInjector(), callback);
executor.execute(list, payload);
return executed;
}

/**
* @inheritDoc
*/
public function detain(command:Object):void
{
_context.detain(command);
}

/**
* @inheritDoc
*/
public function release(command:Object):void
{
_context.release(command);
}

/*============================================================================*/
/* Private Functions */
/*============================================================================*/

private function parseMappingFromClassOrConfig(commandClassOrConfig:*):ICommandMapping
{
var mapping:ICommandMapping;
if ('getMapping' in commandClassOrConfig)
{
mapping = commandClassOrConfig.getMapping();
}
else
{
const commandClass:Class = commandClassOrConfig as Class;
commandClass && (mapping = new CommandMapping(commandClass));
}
return mapping;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
// Copyright (c) 2009-2013 the original author or authors. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//------------------------------------------------------------------------------

package robotlegs.bender.extensions.commandCenter.impl
{
/**
* @author creynder
*/
import robotlegs.bender.extensions.commandCenter.api.ICommandMapping;
import robotlegs.bender.extensions.commandCenter.dsl.ICommandConfigurator;
import robotlegs.bender.extensions.commandCenter.dsl.IOnceCommandConfig;

public class OnceCommandConfig implements IOnceCommandConfig
{

/*============================================================================*/
/* Private Properties */
/*============================================================================*/

private var _mapping:ICommandMapping;

/*============================================================================*/
/* Constructor */
/*============================================================================*/

public function OnceCommandConfig(commandClass:Class)
{
_mapping = new CommandMapping(commandClass);
_mapping.setFireOnce(true);
}

/*============================================================================*/
/* Public Functions */
/*============================================================================*/

public function getMapping():ICommandMapping
{
return _mapping;
}

/**
* @inheritDoc
*/
public function withExecuteMethod(name:String):IOnceCommandConfig
{
_mapping.setExecuteMethod(name);
return this;
}

/**
* @inheritDoc
*/
public function withGuards(... guards):IOnceCommandConfig
{
_mapping.addGuards.apply(null, guards);
return this;
}

/**
* @inheritDoc
*/
public function withHooks(... hooks):IOnceCommandConfig
{
_mapping.addHooks.apply(null, hooks);
return this;
}

/**
* @inheritDoc
*/
public function withPayloadInjection(value:Boolean=true):IOnceCommandConfig
{
_mapping.setPayloadInjectionEnabled(value);
return this;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
// Copyright (c) 2011 the original author or authors. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//------------------------------------------------------------------------------

package robotlegs.bender.extensions.commandCenter
{
import org.flexunit.assertThat;
import org.hamcrest.object.instanceOf;
import robotlegs.bender.extensions.commandCenter.api.ICommandCenter;
import robotlegs.bender.extensions.eventDispatcher.EventDispatcherExtension;
import robotlegs.bender.framework.impl.Context;

public class CommandCenterExtensionTest
{

/*============================================================================*/
/* Private Properties */
/*============================================================================*/

private var context:Context;

/*============================================================================*/
/* Test Setup and Teardown */
/*============================================================================*/

[Before]
public function before():void
{
context = new Context();
context.install(EventDispatcherExtension, CommandCenterExtension);
}

/*============================================================================*/
/* Tests */
/*============================================================================*/

[Test]
public function commandCenter_is_mapped_into_injector():void
{
var actual:Object = null;
context.whenInitializing( function():void {
actual = context.injector.getInstance(ICommandCenter);
});
context.initialize();
assertThat(actual, instanceOf(ICommandCenter));
}
}
}
Loading

0 comments on commit 13df873

Please sign in to comment.