Permalink
Browse files

fleshes out new lifecycle

  • Loading branch information...
1 parent 00060be commit 6d2a12d26e07db5a2de9a24ef3627ee2ac5e00a1 @darscan darscan committed Apr 30, 2012
@@ -39,22 +39,51 @@ package robotlegs.bender.framework.lifecycle
private var _reversePriority:int;
+ private var _initialize:LifecycleTransition;
+
+ private var _suspend:LifecycleTransition;
+
+ private var _resume:LifecycleTransition;
+
+ private var _destroy:LifecycleTransition;
+
/*============================================================================*/
/* Constructor */
/*============================================================================*/
public function Lifecycle(target:Object)
{
_target = target;
+ configureTransitions();
}
/*============================================================================*/
/* Public Functions */
/*============================================================================*/
+ public function initialize(callback:Function = null):void
+ {
+ _initialize.enter(callback);
+ }
+
+ public function suspend(callback:Function = null):void
+ {
+ _suspend.enter(callback);
+ }
+
+ public function resume(callback:Function = null):void
+ {
+ _resume.enter(callback);
+ }
+
+ public function destroy(callback:Function = null):void
+ {
+ _destroy.enter(callback);
+ }
+
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
{
- priority = modPriority(type, priority);
+ priority = flipPriority(type, priority);
super.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
@@ -67,7 +96,7 @@ package robotlegs.bender.framework.lifecycle
if (_state == state)
return;
_state = state;
-
+ // todo: dispatch LifecycleEvent.STATE_CHANGE
}
internal function addReversedEventTypes(... types):void
@@ -80,7 +109,30 @@ package robotlegs.bender.framework.lifecycle
/* Private Functions */
/*============================================================================*/
- private function modPriority(type:String, priority:int):int
+ private function configureTransitions():void
+ {
+ _initialize = new LifecycleTransition("initialize", this)
+ .fromStates(LifecycleState.UNINITIALIZED)
+ .toStates(LifecycleState.INITIALIZING, LifecycleState.ACTIVE)
+ .withEvents(LifecycleEvent.PRE_INITIALIZE, LifecycleEvent.INITIALIZE, LifecycleEvent.POST_INITIALIZE);
+
+ _suspend = new LifecycleTransition("suspend", this)
+ .fromStates(LifecycleState.ACTIVE)
+ .toStates(LifecycleState.SUSPENDING, LifecycleState.SUSPENDED)
+ .withEvents(LifecycleEvent.PRE_SUSPEND, LifecycleEvent.SUSPEND, LifecycleEvent.POST_SUSPEND);
+
+ _resume = new LifecycleTransition("resume", this)
+ .fromStates(LifecycleState.SUSPENDED)
+ .toStates(LifecycleState.RESUMING, LifecycleState.ACTIVE)
+ .withEvents(LifecycleEvent.PRE_RESUME, LifecycleEvent.RESUME, LifecycleEvent.POST_RESUME);
+
+ _destroy = new LifecycleTransition("destroy", this)
+ .fromStates(LifecycleState.SUSPENDED, LifecycleState.ACTIVE)
+ .toStates(LifecycleState.DESTROYING, LifecycleState.DESTROYED)
+ .withEvents(LifecycleEvent.PRE_DESTROY, LifecycleEvent.DESTROY, LifecycleEvent.POST_DESTROY);
+ }
+
+ private function flipPriority(type:String, priority:int):int
{
return (priority == 0 && _reversedEventTypes[type])
? _reversePriority++
@@ -16,13 +16,31 @@ package robotlegs.bender.framework.lifecycle
/* Public Static Properties */
/*============================================================================*/
+ public static const ERROR:String = "error";
+
public static const PRE_INITIALIZE:String = "preInitialize";
public static const INITIALIZE:String = "initialize";
public static const POST_INITIALIZE:String = "postInitialize";
- public static const ERROR:String = "error";
+ public static const PRE_SUSPEND:String = "preSuspend";
+
+ public static const SUSPEND:String = "suspend";
+
+ public static const POST_SUSPEND:String = "postSuspend";
+
+ public static const PRE_RESUME:String = "preResume";
+
+ public static const RESUME:String = "resume";
+
+ public static const POST_RESUME:String = "postResume";
+
+ public static const PRE_DESTROY:String = "preDestroy";
+
+ public static const DESTROY:String = "destroy";
+
+ public static const POST_DESTROY:String = "postDestroy";
/*============================================================================*/
/* Public Properties */
@@ -20,5 +20,15 @@ package robotlegs.bender.framework.lifecycle
public static const INITIALIZING:String = "initializing";
public static const ACTIVE:String = "active";
+
+ public static const SUSPENDING:String = "suspending";
+
+ public static const SUSPENDED:String = "suspended";
+
+ public static const RESUMING:String = "resuming";
+
+ public static const DESTROYING:String = "destroying";
+
+ public static const DESTROYED:String = "destroyed";
}
}
@@ -134,8 +134,7 @@ package robotlegs.bender.framework.lifecycle
// run before handlers
_dispatcher.dispatchMessage(_name, function(error:Object):void
{
-
- // revert state and report error
+ // revert state, report error, and exit
if (error)
{
setState(initialState);
@@ -8,6 +8,7 @@
package robotlegs.bender.framework.lifecycle
{
import org.hamcrest.assertThat;
+ import org.hamcrest.collection.array;
import org.hamcrest.object.equalTo;
public class LifecycleTest
@@ -47,5 +48,138 @@ package robotlegs.bender.framework.lifecycle
{
assertThat(lifecycle.target, equalTo(target));
}
+
+ // ----- Basic valid transitions
+
+ [Test]
+ public function initialize_turns_state_active():void
+ {
+ lifecycle.initialize();
+ assertThat(lifecycle.state, equalTo(LifecycleState.ACTIVE));
+ }
+
+ [Test]
+ public function suspend_turns_state_suspended():void
+ {
+ lifecycle.initialize();
+ lifecycle.suspend();
+ assertThat(lifecycle.state, equalTo(LifecycleState.SUSPENDED));
+ }
+
+ [Test]
+ public function resume_turns_state_active():void
+ {
+ lifecycle.initialize();
+ lifecycle.suspend();
+ lifecycle.resume();
+ assertThat(lifecycle.state, equalTo(LifecycleState.ACTIVE));
+ }
+
+ [Test]
+ public function destroy_turns_state_destroyed():void
+ {
+ lifecycle.initialize();
+ lifecycle.destroy();
+ assertThat(lifecycle.state, equalTo(LifecycleState.DESTROYED));
+ }
+
+ [Test]
+ public function typical_transition_chain_does_not_throw_errors():void
+ {
+ const methods:Array = [
+ lifecycle.initialize,
+ lifecycle.suspend,
+ lifecycle.resume,
+ lifecycle.suspend,
+ lifecycle.resume,
+ lifecycle.destroy];
+ assertThat(methodErrorCount(methods), equalTo(0));
+ }
+
+ // ----- Invalid transitions
+
+ [Test]
+ public function from_uninitialized___suspend_resume_and_destroy_throw_errors():void
+ {
+ const methods:Array = [
+ lifecycle.suspend,
+ lifecycle.resume,
+ lifecycle.destroy];
+ assertThat(methodErrorCount(methods), equalTo(3));
+ }
+
+ [Test(expects="Error")]
+ public function from_suspended___initialize_throws_error():void
+ {
+ lifecycle.initialize();
+ lifecycle.suspend();
+ lifecycle.initialize();
+ }
+
+ [Test]
+ public function from_destroyed___initialize_suspend_and_resume_throw_errors():void
+ {
+ const methods:Array = [
+ lifecycle.initialize,
+ lifecycle.suspend,
+ lifecycle.resume];
+ lifecycle.initialize();
+ lifecycle.destroy();
+ assertThat(methodErrorCount(methods), equalTo(3));
+ }
+
+ // ----- Events
+
+ [Test]
+ public function events_are_dispatched():void
+ {
+ const actual:Array = [];
+ const expected:Array = [
+ LifecycleEvent.PRE_INITIALIZE,
+ LifecycleEvent.INITIALIZE,
+ LifecycleEvent.POST_INITIALIZE,
+ LifecycleEvent.PRE_SUSPEND,
+ LifecycleEvent.SUSPEND,
+ LifecycleEvent.POST_SUSPEND,
+ LifecycleEvent.PRE_RESUME,
+ LifecycleEvent.RESUME,
+ LifecycleEvent.POST_RESUME,
+ LifecycleEvent.PRE_DESTROY,
+ LifecycleEvent.DESTROY,
+ LifecycleEvent.POST_DESTROY
+ ];
+ const listener:Function = function(event:LifecycleEvent):void{
+ actual.push(event.type);
+ };
+ for each (var type:String in expected) {
+ lifecycle.addEventListener(type, listener);
+ }
+ lifecycle.initialize();
+ lifecycle.suspend();
+ lifecycle.resume();
+ lifecycle.destroy();
+ assertThat(actual, array(expected));
+ }
+
+ /*============================================================================*/
+ /* Private Functions */
+ /*============================================================================*/
+
+ private function methodErrorCount(methods:Array):int
+ {
+ var errorCount:int = 0;
+ for each (var method:Function in methods)
+ {
+ try
+ {
+ method();
+ }
+ catch (error:Error)
+ {
+ errorCount++;
+ }
+ }
+ return errorCount;
+ }
}
}
@@ -22,8 +22,6 @@ package robotlegs.bender.framework.lifecycle
/* Private Properties */
/*============================================================================*/
- private var target:Object;
-
private var lifecycle:Lifecycle;
private var transition:LifecycleTransition;
@@ -35,7 +33,7 @@ package robotlegs.bender.framework.lifecycle
[Before]
public function before():void
{
- target = new Object();
+ const target:Object = new Object();
lifecycle = new Lifecycle(target);
transition = new LifecycleTransition("test", lifecycle);
}

0 comments on commit 6d2a12d

Please sign in to comment.