├── .gitattributes ├── libs ├── hamcrest-as3-only-1.1.3.swc ├── flexUnitTasks-4.2.0-20140410.jar ├── robotlegs-framework-v2.2.1.swc ├── flexunit-4.2.0-20140410-flex_4.12.0.swc ├── flexunit-cilistener-4.2.0-20140410-4.12.0.swc └── flexunit-uilistener-4.2.0-20140410-4.12.0.swc ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── user.properties.eg └── template.properties ├── settings.gradle ├── .gitignore ├── src ├── main │ └── actionscript │ │ └── eu │ │ └── alebianco │ │ └── robotlegs │ │ └── utils │ │ ├── dsl │ │ ├── ISubCommandUnMapper.as │ │ ├── ISubCommandMapper.as │ │ ├── ISubCommandConfigurator.as │ │ └── ISubCommandMappingList.as │ │ ├── api │ │ ├── IAsyncCommand.as │ │ ├── IMacro.as │ │ └── ISubCommandMapping.as │ │ └── impl │ │ ├── SubCommandInstanceMapping.as │ │ ├── AsyncCommand.as │ │ ├── SubCommandPayload.as │ │ ├── ParallelMacro.as │ │ ├── SequenceMacro.as │ │ ├── SubCommandMapping.as │ │ ├── SubCommandMappingList.as │ │ └── AbstractMacro.as └── test │ └── actionscript │ └── eu │ └── alebianco │ └── robotlegs │ └── utils │ ├── support │ ├── MacroWithNumberPayload.as │ ├── MacroWithSimplePayload.as │ ├── TestStringCommand.as │ ├── TestIntCommand.as │ ├── TestXMLCommand.as │ ├── TestNumberCommand.as │ ├── TestXMLListCommand.as │ ├── MacroWithPseudoNullPayload.as │ ├── SimpleAsyncCommand.as │ ├── TestNameStringCommand.as │ ├── MacroWithNamedPayload.as │ ├── MacroWithSimpleCallback.as │ └── MacroWithXMLPayload.as │ ├── AsyncCallbackTest.as │ ├── InstanceTest.as │ └── PayloadsTest.as ├── CHANGELOG.md ├── .travis.yml ├── LICENSE.md ├── gradlew.bat ├── CONTRIBUTING.md ├── gradlew └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.swc -crlf -diff 2 | -------------------------------------------------------------------------------- /libs/hamcrest-as3-only-1.1.3.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alebianco/robotlegs-utilities-macrobot/HEAD/libs/hamcrest-as3-only-1.1.3.swc -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alebianco/robotlegs-utilities-macrobot/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /libs/flexUnitTasks-4.2.0-20140410.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alebianco/robotlegs-utilities-macrobot/HEAD/libs/flexUnitTasks-4.2.0-20140410.jar -------------------------------------------------------------------------------- /libs/robotlegs-framework-v2.2.1.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alebianco/robotlegs-utilities-macrobot/HEAD/libs/robotlegs-framework-v2.2.1.swc -------------------------------------------------------------------------------- /libs/flexunit-4.2.0-20140410-flex_4.12.0.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alebianco/robotlegs-utilities-macrobot/HEAD/libs/flexunit-4.2.0-20140410-flex_4.12.0.swc -------------------------------------------------------------------------------- /libs/flexunit-cilistener-4.2.0-20140410-4.12.0.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alebianco/robotlegs-utilities-macrobot/HEAD/libs/flexunit-cilistener-4.2.0-20140410-4.12.0.swc -------------------------------------------------------------------------------- /libs/flexunit-uilistener-4.2.0-20140410-4.12.0.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alebianco/robotlegs-utilities-macrobot/HEAD/libs/flexunit-uilistener-4.2.0-20140410-4.12.0.swc -------------------------------------------------------------------------------- /gradle/user.properties.eg: -------------------------------------------------------------------------------- 1 | mac.flash.player = /Applications/Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger 2 | win.flash.player = C:/Program Files (x86)/Apache Flex/player/win/15.0.0.152/flashplayer_15_sa_debug.exe 3 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Project: robotlegs-utilities-macrobot 3 | * 4 | * Author: Alessandro Bianco 5 | * Website: http://alessandrobianco.eu 6 | * Twitter: @alebianco 7 | * Created: 18/10/2014 14.54 8 | */ 9 | 10 | rootProject.name = 'robotlegs-utilities-macrobot' 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Oct 18 17:14:56 BST 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /doc 3 | /build 4 | /release 5 | 6 | .actionScriptProperties 7 | .flexProperties 8 | .flexLibProperties 9 | .FlexUnitSettings 10 | .project 11 | .fxpProperties 12 | 13 | user.properties 14 | 15 | Icon 16 | Thumbs.db 17 | .DS_Store 18 | 19 | .idea 20 | *.iml 21 | /out -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/dsl/ISubCommandUnMapper.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: alessandro.bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 12/06/2013 11:24 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.dsl { 10 | public interface ISubCommandUnMapper { 11 | function remove(commandClass:Class):void; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/dsl/ISubCommandMapper.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: alessandro.bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 12/06/2013 11:24 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.dsl { 10 | 11 | public interface ISubCommandMapper { 12 | function add(commandClass:Class):ISubCommandConfigurator; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gradle/template.properties: -------------------------------------------------------------------------------- 1 | product.name = Macrobot 2 | product.version = 0.9.71 3 | product.group = eu.alebianco 4 | product.title = Macro Commands For Robotlegs2 5 | product.description = Macro command utility for Robotlegs which provides the ability to execute batches of commands in sequential or parallel fashion. 6 | product.copyright = Copyright (c) 2011 - 2014 Alessandro Bianco 7 | repository.url = https://github.com/alebianco/robotlegs-utilities-macrobot 8 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/api/IAsyncCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 26/07/12 8.32 6 | * 7 | * Copyright © 2011 - 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.api { 10 | import robotlegs.bender.extensions.commandCenter.api.ICommand; 11 | 12 | public interface IAsyncCommand extends ICommand { 13 | function registerCompleteCallback(callback:Function):void; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/api/IMacro.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 26/07/12 8.32 6 | * 7 | * Copyright © 2011 - 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.api { 10 | 11 | import eu.alebianco.robotlegs.utils.dsl.ISubCommandMapper; 12 | import eu.alebianco.robotlegs.utils.dsl.ISubCommandUnMapper; 13 | 14 | import robotlegs.bender.extensions.commandCenter.api.ICommand; 15 | 16 | public interface IMacro extends ICommand, ISubCommandMapper, ISubCommandUnMapper { 17 | function prepare():void; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/dsl/ISubCommandConfigurator.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: alessandro.bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 12/06/2013 11:24 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.dsl { 10 | public interface ISubCommandConfigurator { 11 | 12 | function withGuards(...guards):ISubCommandConfigurator; 13 | 14 | function withHooks(...hooks):ISubCommandConfigurator; 15 | 16 | function withPayloads(...payloads):ISubCommandConfigurator; 17 | 18 | function withExecuteMethod(name:String):ISubCommandConfigurator; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/impl/SubCommandInstanceMapping.as: -------------------------------------------------------------------------------- 1 | package eu.alebianco.robotlegs.utils.impl { 2 | import robotlegs.bender.extensions.commandCenter.api.ICommand; 3 | import robotlegs.bender.framework.api.IInjector; 4 | 5 | public class SubCommandInstanceMapping extends SubCommandMapping { 6 | 7 | private var _instance : ICommand; 8 | 9 | public function SubCommandInstanceMapping(instance:ICommand) { 10 | _instance = instance; 11 | super(Object(instance).constructor); 12 | } 13 | 14 | override public function getOrCreateCommandInstance(injector : IInjector) : ICommand { 15 | injector.injectInto(_instance); 16 | return _instance; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/MacroWithNumberPayload.as: -------------------------------------------------------------------------------- 1 | /**= 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:52 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import eu.alebianco.robotlegs.utils.impl.SequenceMacro; 11 | 12 | public class MacroWithNumberPayload extends SequenceMacro { 13 | [Inject(name="reportingFunction")] 14 | public var reportingFunc:Function; 15 | 16 | override public function prepare():void { 17 | reportingFunc(MacroWithNumberPayload); 18 | add(TestNumberCommand).withPayloads(Math.PI); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/MacroWithSimplePayload.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:49 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import eu.alebianco.robotlegs.utils.impl.SequenceMacro; 11 | 12 | public class MacroWithSimplePayload extends SequenceMacro { 13 | 14 | [Inject(name="reportingFunction")] 15 | public var reportingFunc:Function; 16 | 17 | override public function prepare():void { 18 | reportingFunc(MacroWithSimplePayload); 19 | add(TestStringCommand).withPayloads("world"); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/dsl/ISubCommandMappingList.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: alessandro.bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 11/06/2013 14:50 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.dsl { 10 | import eu.alebianco.robotlegs.utils.api.*; 11 | 12 | public interface ISubCommandMappingList { 13 | function addMapping(mapping:ISubCommandMapping):void; 14 | 15 | function removeMapping(mapping:ISubCommandMapping):void; 16 | 17 | function removeMappingsFor(commandClass:Class):void; 18 | 19 | function removeAllMappings():void; 20 | 21 | function getList():Vector.; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## HEAD 2 | 3 | ### 0.9.71 (October 19, 2013) 4 | 5 | * Moved to a Gradle powered build system 6 | 7 | ### 0.9.7 (October 18, 2013) 8 | 9 | * updated to Robotlegs 2.2.1 10 | * merged pull request #13 - added possibility to map an instance 11 | 12 | ### 0.9.6 (August 10, 2013) 13 | 14 | * updated to Robotlegs 2.1.0 15 | * fixed issue with mapping payloads using raw data 16 | * added the first two tests (yay!) in the suite to cover the payload issue 17 | 18 | ### 0.9.5 (June 16, 2013) 19 | 20 | * complete refactoring 21 | * fixed bug with payloads unavailable to guards 22 | * updated to use robotlegs 2.0.0b8 23 | 24 | ### 0.9.0 (April 14, 2013) 25 | 26 | * Initial release 27 | * Implemented Async commands 28 | * Implemented Parallel macros 29 | * Implemented Sequence macros 30 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/api/ISubCommandMapping.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 26/07/12 8.32 6 | * 7 | * Copyright © 2011 - 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.api { 10 | import robotlegs.bender.extensions.commandCenter.api.ICommand; 11 | import robotlegs.bender.framework.api.IInjector; 12 | 13 | public interface ISubCommandMapping { 14 | function get commandClass():Class; 15 | 16 | function get executeMethod():String; 17 | 18 | function get guards():Array; 19 | 20 | function get hooks():Array; 21 | 22 | function get payloads():Array; 23 | 24 | function getOrCreateCommandInstance(injector : IInjector) : ICommand; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/TestStringCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:50 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import robotlegs.bender.bundles.mvcs.Command; 11 | 12 | public class TestStringCommand extends Command { 13 | 14 | [Inject] 15 | public var who:String; 16 | 17 | [Inject(name="reportingFunction")] 18 | public var reportingFunc:Function; 19 | 20 | [PostConstruct] 21 | public function init():void { 22 | reportingFunc(TestStringCommand) 23 | } 24 | 25 | override public function execute():void { 26 | reportingFunc(who) 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/TestIntCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:52 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import robotlegs.bender.bundles.mvcs.Command; 11 | 12 | public class TestIntCommand extends Command { 13 | 14 | [Inject] 15 | public var number:int; 16 | 17 | [Inject(name="reportingFunction")] 18 | public var reportingFunc:Function; 19 | 20 | [PostConstruct] 21 | public function init():void { 22 | reportingFunc(TestIntCommand); 23 | } 24 | 25 | override public function execute():void { 26 | reportingFunc(number); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/TestXMLCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:52 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import robotlegs.bender.bundles.mvcs.Command; 11 | 12 | public class TestXMLCommand extends Command { 13 | 14 | [Inject] 15 | public var data:XML; 16 | 17 | [Inject(name="reportingFunction")] 18 | public var reportingFunc:Function; 19 | 20 | [PostConstruct] 21 | public function init():void { 22 | reportingFunc(TestXMLCommand); 23 | } 24 | 25 | override public function execute():void { 26 | reportingFunc(data.@key); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/TestNumberCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:52 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import robotlegs.bender.bundles.mvcs.Command; 11 | 12 | public class TestNumberCommand extends Command { 13 | 14 | [Inject] 15 | public var number:Number; 16 | 17 | [Inject(name="reportingFunction")] 18 | public var reportingFunc:Function; 19 | 20 | [PostConstruct] 21 | public function init():void { 22 | reportingFunc(TestNumberCommand); 23 | } 24 | 25 | override public function execute():void { 26 | reportingFunc(number); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/TestXMLListCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:52 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import robotlegs.bender.bundles.mvcs.Command; 11 | 12 | public class TestXMLListCommand extends Command { 13 | 14 | [Inject] 15 | public var data:XMLList; 16 | 17 | [Inject(name="reportingFunction")] 18 | public var reportingFunc:Function; 19 | 20 | [PostConstruct] 21 | public function init():void { 22 | reportingFunc(TestXMLListCommand); 23 | } 24 | 25 | override public function execute():void { 26 | reportingFunc(data.length()); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/MacroWithPseudoNullPayload.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:56 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import eu.alebianco.robotlegs.utils.impl.SequenceMacro; 11 | 12 | public class MacroWithPseudoNullPayload extends SequenceMacro { 13 | [Inject(name="reportingFunction")] 14 | public var reportingFunc:Function; 15 | 16 | override public function prepare():void { 17 | reportingFunc(MacroWithPseudoNullPayload); 18 | add(TestStringCommand).withPayloads(""); 19 | add(TestIntCommand).withPayloads(0); 20 | add(TestNumberCommand).withPayloads(NaN); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/SimpleAsyncCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 13/03/2014 14:45 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import eu.alebianco.robotlegs.utils.impl.AsyncCommand; 11 | 12 | import flash.utils.setTimeout; 13 | 14 | public class SimpleAsyncCommand extends AsyncCommand { 15 | 16 | [Inject(name="reportingFunction")] 17 | public var reportingFunc:Function; 18 | 19 | [PostConstruct] 20 | public function init():void { 21 | reportingFunc(SimpleAsyncCommand); 22 | } 23 | 24 | override public function execute():void { 25 | setTimeout(dispatchComplete, 100, true); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/TestNameStringCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:51 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import robotlegs.bender.bundles.mvcs.Command; 11 | 12 | public class TestNameStringCommand extends Command { 13 | 14 | [Inject(name="target")] 15 | public var who:String; 16 | 17 | [Inject(name="reportingFunction")] 18 | public var reportingFunc:Function; 19 | 20 | [PostConstruct] 21 | public function init():void { 22 | reportingFunc(TestNameStringCommand) 23 | } 24 | 25 | override public function execute():void { 26 | reportingFunc(who) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/MacroWithNamedPayload.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:51 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import eu.alebianco.robotlegs.utils.impl.SequenceMacro; 11 | import eu.alebianco.robotlegs.utils.impl.SubCommandPayload; 12 | 13 | public class MacroWithNamedPayload extends SequenceMacro { 14 | [Inject(name="reportingFunction")] 15 | public var reportingFunc:Function; 16 | 17 | override public function prepare():void { 18 | reportingFunc(MacroWithNamedPayload); 19 | var payload:SubCommandPayload = new SubCommandPayload("world", String).withName("target"); 20 | add(TestNameStringCommand).withPayloads(payload); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Project: robotlegs-utilities-macrobot 3 | # 4 | # Author: Alessandro Bianco 5 | # Website: http://alessandrobianco.eu 6 | # Twitter: @alebianco 7 | # Created: 18/10/2014 23.12 8 | # 9 | 10 | language: objective-c 11 | 12 | git: 13 | depth: 1 14 | 15 | env: 16 | - TERM=dumb 17 | 18 | deploy: 19 | provider: releases 20 | api-key: 21 | secure: "iOHRj8qngFQe67OJ9DcJVvSlf/9qI+rySL9BX1fr/yF3/n1qCmengC90h76DfreU7ZfmTj8vyzVrfEDWQeZPUeOeAQVON1XwktUDY2LfsjAfgsuJXzwYzx4pPBAF8I6nWlaC0ta1vr+irIbZ8sRY2lS/vZY6Oeo0mreWbIKOKck=" 22 | file: "release/*.zip" 23 | file_glob: true 24 | skip_cleanup: true 25 | on: 26 | tags: true 27 | all_branches: true 28 | 29 | before_install: 30 | - brew update >brew-update.log 31 | - chmod +x gradlew 32 | 33 | install: 34 | - brew install caskroom/cask/brew-cask 35 | - brew cask install flash-player-debugger 36 | 37 | before_script: 38 | - export FLASH_PLAYER_EXE="$HOME/Applications/Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger" 39 | 40 | script: ./gradlew release -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/MacroWithSimpleCallback.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 13/03/2014 14:42 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import eu.alebianco.robotlegs.utils.impl.SequenceMacro; 11 | 12 | import flash.events.Event; 13 | 14 | import flash.events.IEventDispatcher; 15 | 16 | public class MacroWithSimpleCallback extends SequenceMacro { 17 | 18 | [Inject(name="reportingFunction")] 19 | public var reportingFunc:Function; 20 | 21 | [Inject] 22 | public var dispatcher:IEventDispatcher; 23 | 24 | override public function prepare():void { 25 | registerCompleteCallback(onSimpleComplete); 26 | 27 | reportingFunc(MacroWithSimpleCallback); 28 | add(SimpleAsyncCommand); 29 | } 30 | 31 | private function onSimpleComplete():void { 32 | dispatcher.dispatchEvent(new Event(Event.COMPLETE)); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011 - 2014 the original author or authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/support/MacroWithXMLPayload.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 03/02/2014 10:56 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.support { 10 | import eu.alebianco.robotlegs.utils.impl.SequenceMacro; 11 | 12 | public class MacroWithXMLPayload extends SequenceMacro { 13 | [Inject(name="reportingFunction")] 14 | public var reportingFunc:Function; 15 | 16 | override public function prepare():void { 17 | 18 | const data:XML = 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | reportingFunc(MacroWithXMLPayload); 29 | add(TestXMLCommand).withPayloads(data); 30 | add(TestXMLListCommand).withPayloads(data.color.@name); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/impl/AsyncCommand.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 26/07/12 8.32 6 | * 7 | * Copyright © 2011 - 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.impl { 10 | 11 | import eu.alebianco.robotlegs.utils.api.IAsyncCommand; 12 | 13 | import robotlegs.bender.framework.api.IContext; 14 | 15 | public class AsyncCommand implements IAsyncCommand { 16 | protected var listeners:Array; 17 | 18 | [Inject] 19 | public var context:IContext; 20 | 21 | public function registerCompleteCallback(listener:Function):void { 22 | listeners ||= []; 23 | listeners.unshift(listener); 24 | } 25 | 26 | public function execute():void { 27 | context.detain(this); 28 | } 29 | 30 | protected function dispatchComplete(success:Boolean):void { 31 | context.release(this); 32 | for each (var listener:Function in listeners) { 33 | if (listener.length == 0) { 34 | listener(); 35 | } else { 36 | listener(success); 37 | } 38 | } 39 | if (listeners) { 40 | listeners.length = 0; 41 | listeners = null; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/impl/SubCommandPayload.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 26/07/12 8.32 6 | * 7 | * Copyright © 2011 - 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.impl { 10 | import org.swiftsuspenders.reflection.DescribeTypeReflector; 11 | import org.swiftsuspenders.reflection.Reflector; 12 | 13 | final public class SubCommandPayload { 14 | private var _data:*; 15 | private var _type:Class; 16 | private var _name:String; 17 | 18 | private static var _reflector:Reflector; 19 | private function get reflector():Reflector { 20 | return _reflector ||= new DescribeTypeReflector(); 21 | } 22 | 23 | public function SubCommandPayload(data:*, type:Class = null) { 24 | if (data == null || data == undefined) { 25 | throw new ArgumentError("Payload data can't be null"); 26 | } 27 | _data = data; 28 | _type = type; 29 | } 30 | 31 | public function get name():String { 32 | return _name || ""; 33 | } 34 | 35 | public function get type():Class { 36 | return _type ||= reflector.getClass(data); 37 | } 38 | 39 | public function get data():* { 40 | return _data; 41 | } 42 | 43 | public function withName(name:String):SubCommandPayload { 44 | _name = name; 45 | return this; 46 | } 47 | 48 | public function ofClass(type:Class):SubCommandPayload { 49 | _type = type; 50 | return this; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/impl/ParallelMacro.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 26/07/12 8.32 6 | * 7 | * Copyright © 2011 - 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.impl { 10 | 11 | import eu.alebianco.robotlegs.utils.api.IMacro; 12 | import eu.alebianco.robotlegs.utils.api.ISubCommandMapping; 13 | 14 | public class ParallelMacro extends AbstractMacro implements IMacro { 15 | 16 | protected var executionCount:uint = 0; 17 | 18 | protected var commands:Vector.; 19 | 20 | protected var success:Boolean = true; 21 | protected var running:Boolean = false; 22 | 23 | override public function execute():void { 24 | super.execute(); 25 | commands = mappings.getList(); 26 | if (hasCommands) { 27 | running = true; 28 | for each (var mapping:ISubCommandMapping in commands) { 29 | if (!success) break; 30 | executeCommand(mapping); 31 | } 32 | } else { 33 | dispatchComplete(true); 34 | } 35 | } 36 | 37 | protected function get hasCommands():Boolean { 38 | return mappings && commands.length > 0; 39 | } 40 | 41 | override protected function commandCompleteHandler(success:Boolean):void { 42 | executionCount++; 43 | this.success &&= success; 44 | if (running && (!this.success || executionCount == commands.length)) { 45 | dispatchComplete(this.success); 46 | } 47 | } 48 | 49 | override protected function dispatchComplete(success:Boolean):void { 50 | super.dispatchComplete(success); 51 | running = false; 52 | this.success = true; 53 | executionCount = 0; 54 | commands = null; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/impl/SequenceMacro.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 26/07/12 8.32 6 | * 7 | * Copyright © 2011 - 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.impl { 10 | 11 | import eu.alebianco.robotlegs.utils.api.IMacro; 12 | import eu.alebianco.robotlegs.utils.api.ISubCommandMapping; 13 | 14 | public class SequenceMacro extends AbstractMacro implements IMacro { 15 | 16 | protected var executionIndex:uint; 17 | 18 | protected var success:Boolean = true; 19 | protected var running:Boolean = false; 20 | 21 | protected var commands:Vector.; 22 | 23 | private var _atomic:Boolean = true; 24 | public function get atomic():Boolean { 25 | return _atomic; 26 | } 27 | 28 | public function set atomic(value:Boolean):void { 29 | if (!running) { 30 | _atomic = value; 31 | } 32 | } 33 | 34 | override public function execute():void { 35 | super.execute(); 36 | running = true; 37 | executionIndex = 0; 38 | commands = mappings.getList(); 39 | executeNext(); 40 | } 41 | 42 | protected function executeNext():void { 43 | if (hasCommands) { 44 | const mapping:ISubCommandMapping = commands[executionIndex++]; 45 | executeCommand(mapping); 46 | } else { 47 | dispatchComplete(success); 48 | } 49 | } 50 | 51 | protected function get hasCommands():Boolean { 52 | return commands && executionIndex < commands.length; 53 | } 54 | 55 | override protected function commandCompleteHandler(success:Boolean):void { 56 | this.success &&= success; 57 | (_atomic || this.success) ? executeNext() : dispatchComplete(false); 58 | } 59 | 60 | override protected function dispatchComplete(success:Boolean):void { 61 | super.dispatchComplete(success); 62 | running = false; 63 | this.success = true; 64 | executionIndex = 0; 65 | commands = null; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/impl/SubCommandMapping.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 26/07/12 8.32 6 | * 7 | * Copyright © 2011 - 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.impl { 10 | import eu.alebianco.robotlegs.utils.api.ISubCommandMapping; 11 | import eu.alebianco.robotlegs.utils.dsl.ISubCommandConfigurator; 12 | 13 | import robotlegs.bender.extensions.commandCenter.api.ICommand; 14 | import robotlegs.bender.framework.api.IInjector; 15 | 16 | internal class SubCommandMapping implements ISubCommandMapping, ISubCommandConfigurator { 17 | 18 | private var _commandClass:Class; 19 | private var _executeMethod:String = 'execute'; 20 | 21 | private var _guards:Array = []; 22 | private var _payloads:Array = []; 23 | private var _hooks:Array = []; 24 | 25 | public function SubCommandMapping(commandClass:Class) { 26 | _commandClass = commandClass; 27 | } 28 | 29 | public function get commandClass():Class { 30 | return _commandClass; 31 | } 32 | 33 | public function get executeMethod():String { 34 | return _executeMethod; 35 | } 36 | 37 | public function get guards():Array { 38 | return _guards.slice(); 39 | } 40 | 41 | public function get hooks():Array { 42 | return _hooks.slice(); 43 | } 44 | 45 | public function get payloads():Array { 46 | return _payloads.slice(); 47 | } 48 | 49 | public function withGuards(...guards):ISubCommandConfigurator { 50 | _guards = _guards.concat.apply(null, guards); 51 | return this; 52 | } 53 | 54 | public function withHooks(...hooks):ISubCommandConfigurator { 55 | _hooks = _hooks.concat.apply(null, hooks); 56 | return this; 57 | } 58 | 59 | public function withPayloads(...payloads):ISubCommandConfigurator { 60 | for each (var object:Object in payloads) { 61 | var payload:SubCommandPayload; 62 | if (object is SubCommandPayload) { 63 | payload = object as SubCommandPayload; 64 | } else { 65 | payload = new SubCommandPayload(object); 66 | } 67 | _payloads.push(payload); 68 | } 69 | return this; 70 | } 71 | 72 | public function withExecuteMethod(name:String):ISubCommandConfigurator { 73 | _executeMethod = name; 74 | return this; 75 | } 76 | 77 | public function getOrCreateCommandInstance(injector : IInjector) : ICommand { 78 | return injector.getOrCreateNewInstance(commandClass); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/impl/SubCommandMappingList.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: alessandro.bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 12/06/2013 11:27 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils.impl { 10 | import eu.alebianco.robotlegs.utils.api.ISubCommandMapping; 11 | import eu.alebianco.robotlegs.utils.dsl.ISubCommandMappingList; 12 | 13 | import flash.utils.Dictionary; 14 | 15 | final internal class SubCommandMappingList implements ISubCommandMappingList { 16 | 17 | private var _mappings:Vector. = new Vector.; 18 | private var _mappingByCommand:Dictionary = new Dictionary(true); 19 | 20 | public function getList():Vector. { 21 | return _mappings.concat(); 22 | } 23 | 24 | public function addMapping(mapping:ISubCommandMapping):void { 25 | storeMapping(mapping); 26 | } 27 | 28 | public function removeMapping(mapping:ISubCommandMapping):void { 29 | deleteMapping(mapping); 30 | } 31 | 32 | public function removeMappingsFor(commandClass:Class):void { 33 | if (_mappingByCommand[commandClass]) { 34 | const list:Vector. = _mappingByCommand[commandClass]; 35 | var length:int = list.length; 36 | while (length--) { 37 | deleteMapping(list[length]); 38 | } 39 | delete _mappingByCommand[commandClass]; 40 | } 41 | } 42 | 43 | public function removeAllMappings():void { 44 | if (_mappings.length > 0) { 45 | const list:Vector. = _mappings.concat(); 46 | var length:int = list.length; 47 | while (length--) { 48 | deleteMapping(list[length]); 49 | } 50 | } 51 | } 52 | 53 | private function storeMapping(mapping:ISubCommandMapping):void { 54 | if (!_mappingByCommand[mapping.commandClass]) { 55 | _mappingByCommand[mapping.commandClass] = new []; 56 | } 57 | _mappingByCommand[mapping.commandClass].push(mapping); 58 | _mappings.push(mapping); 59 | } 60 | 61 | private function deleteMapping(mapping:ISubCommandMapping):void { 62 | if (_mappingByCommand[mapping.commandClass]) { 63 | _mappingByCommand[mapping.commandClass].splice(_mappings.indexOf(mapping), 1); 64 | if (_mappingByCommand[mapping.commandClass].length == 0) { 65 | delete _mappingByCommand[mapping.commandClass]; 66 | } 67 | } 68 | _mappings.splice(_mappings.indexOf(mapping), 1); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/AsyncCallbackTest.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 13/03/2014 14:40 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils { 10 | import eu.alebianco.robotlegs.utils.support.MacroWithSimpleCallback; 11 | import eu.alebianco.robotlegs.utils.support.SimpleAsyncCommand; 12 | 13 | import flash.events.Event; 14 | import flash.events.EventDispatcher; 15 | import flash.events.IEventDispatcher; 16 | 17 | import org.flexunit.Assert; 18 | 19 | import org.flexunit.async.Async; 20 | import org.hamcrest.assertThat; 21 | import org.hamcrest.collection.array; 22 | 23 | import robotlegs.bender.extensions.commandCenter.api.ICommandMapping; 24 | import robotlegs.bender.extensions.eventCommandMap.api.IEventCommandMap; 25 | import robotlegs.bender.extensions.eventCommandMap.impl.EventCommandMap; 26 | import robotlegs.bender.framework.api.IContext; 27 | import robotlegs.bender.framework.api.IInjector; 28 | import robotlegs.bender.framework.impl.Context; 29 | import robotlegs.bender.framework.impl.RobotlegsInjector; 30 | 31 | public class AsyncCallbackTest { 32 | 33 | private var injector:IInjector; 34 | private var mappings:Vector.; 35 | private var dispatcher:IEventDispatcher; 36 | private var subject:IEventCommandMap; 37 | private var reported:Array; 38 | 39 | private function reportingFunction(item:Object):void { 40 | reported.push(item); 41 | } 42 | 43 | [Before] 44 | public function before():void { 45 | reported = []; 46 | dispatcher = new EventDispatcher(); 47 | const context:IContext = new Context(); 48 | injector = new RobotlegsInjector(); 49 | injector = context.injector; 50 | injector.map(Function, "reportingFunction").toValue(reportingFunction); 51 | injector.map(IEventDispatcher).toValue(dispatcher); 52 | subject = new EventCommandMap(context, dispatcher); 53 | } 54 | 55 | [After] 56 | public function after():void { 57 | injector = null; 58 | } 59 | 60 | [Test(async)] 61 | public function payload_instances_are_mapped():void { 62 | subject.map("trigger", Event).toCommand(MacroWithSimpleCallback); 63 | 64 | const handler:Function = Async.asyncHandler(this, handleComplete, 1000, null, handleTimeout); 65 | dispatcher.addEventListener(Event.COMPLETE, handler, false, 0, true); 66 | 67 | const event:Event = new Event("trigger"); 68 | dispatcher.dispatchEvent(event); 69 | } 70 | 71 | private function handleComplete(event:Event, passThroughData:Object):void { 72 | assertThat(reported, array(MacroWithSimpleCallback, SimpleAsyncCommand)); 73 | } 74 | 75 | private function handleTimeout(passThroughData:Object):void { 76 | Assert.fail("Pending event timed out"); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/InstanceTest.as: -------------------------------------------------------------------------------- 1 | package eu.alebianco.robotlegs.utils { 2 | import flash.events.Event; 3 | import flash.events.EventDispatcher; 4 | import flash.events.IEventDispatcher; 5 | 6 | import org.hamcrest.assertThat; 7 | 8 | import robotlegs.bender.extensions.commandCenter.api.ICommandMapping; 9 | import robotlegs.bender.extensions.eventCommandMap.api.IEventCommandMap; 10 | import robotlegs.bender.extensions.eventCommandMap.impl.EventCommandMap; 11 | import robotlegs.bender.framework.api.IContext; 12 | import robotlegs.bender.framework.api.IInjector; 13 | import robotlegs.bender.framework.impl.Context; 14 | import robotlegs.bender.framework.impl.RobotlegsInjector; 15 | 16 | import org.hamcrest.collection.array; 17 | 18 | public class InstanceTest { 19 | 20 | private var injector : IInjector; 21 | private var mappings : Vector.; 22 | private var dispatcher : IEventDispatcher; 23 | private var subject : IEventCommandMap; 24 | private var reported : Array; 25 | 26 | private function reportingFunction(item : Object) : void { 27 | reported.push(item); 28 | } 29 | 30 | [Before] 31 | public function before() : void { 32 | reported = []; 33 | injector = new RobotlegsInjector(); 34 | const context : IContext = new Context(); 35 | injector = context.injector; 36 | injector.map(Function, "reportingFunction").toValue(reportingFunction); 37 | dispatcher = new EventDispatcher(); 38 | subject = new EventCommandMap(context, dispatcher); 39 | } 40 | 41 | [After] 42 | public function after() : void { 43 | injector = null; 44 | } 45 | 46 | [Test] 47 | public function payload_instances_are_mapped() : void { 48 | subject.map("trigger", Event).toCommand(TestSequence); 49 | const event : Event = new Event("trigger"); 50 | dispatcher.dispatchEvent(event); 51 | assertThat(reported, array("hello", "test", "test", "good buy")); 52 | } 53 | 54 | } 55 | } 56 | import eu.alebianco.robotlegs.utils.impl.ParallelMacro; 57 | import eu.alebianco.robotlegs.utils.impl.SequenceMacro; 58 | 59 | import robotlegs.bender.bundles.mvcs.Command; 60 | 61 | class TestSequence extends SequenceMacro { 62 | 63 | override public function prepare() : void { 64 | add(ReportString).withPayloads("hello"); 65 | var inlineParallelMacro : InlineParallelMacro = new InlineParallelMacro(); 66 | inlineParallelMacro.add(ReportString).withPayloads("test"); 67 | inlineParallelMacro.add(ReportString).withPayloads("test"); 68 | addInstance(inlineParallelMacro); 69 | add(ReportString).withPayloads("good buy"); 70 | } 71 | } 72 | 73 | class ReportString extends Command { 74 | 75 | [Inject(name="reportingFunction")] 76 | public var reportingFunc : Function; 77 | 78 | [Inject] 79 | public var string : String; 80 | 81 | override public function execute() : void { 82 | reportingFunc(string); 83 | } 84 | } 85 | 86 | class InlineParallelMacro extends ParallelMacro { 87 | 88 | override public function prepare() : void { 89 | //suppress throwing error 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/actionscript/eu/alebianco/robotlegs/utils/impl/AbstractMacro.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | \ * 6 | * Copyright © 2011 - 2013 Alessandro Bianco 7 | */ 8 | package eu.alebianco.robotlegs.utils.impl { 9 | 10 | import eu.alebianco.robotlegs.utils.api.IAsyncCommand; 11 | import eu.alebianco.robotlegs.utils.api.IMacro; 12 | import eu.alebianco.robotlegs.utils.api.ISubCommandMapping; 13 | import eu.alebianco.robotlegs.utils.dsl.ISubCommandConfigurator; 14 | 15 | import robotlegs.bender.extensions.commandCenter.api.ICommand; 16 | import robotlegs.bender.framework.api.IInjector; 17 | import robotlegs.bender.framework.impl.applyHooks; 18 | import robotlegs.bender.framework.impl.guardsApprove; 19 | 20 | public class AbstractMacro extends AsyncCommand implements IMacro { 21 | 22 | [Inject] 23 | public var injector:IInjector; 24 | 25 | protected var mappings:SubCommandMappingList = new SubCommandMappingList(); 26 | 27 | [PostConstruct] 28 | public function initialize():void { 29 | this.injector = injector.createChild(); 30 | prepare(); 31 | } 32 | 33 | public function add(commandClass:Class):ISubCommandConfigurator { 34 | const mapping:SubCommandMapping = new SubCommandMapping(commandClass); 35 | mappings.addMapping(mapping); 36 | return mapping; 37 | } 38 | 39 | public function addInstance(command : ICommand) : ISubCommandConfigurator { 40 | const mapping:SubCommandMapping = new SubCommandInstanceMapping(command); 41 | mappings.addMapping(mapping); 42 | return mapping; 43 | } 44 | 45 | public function remove(commandClass:Class):void { 46 | mappings.removeMappingsFor(commandClass); 47 | } 48 | 49 | public function prepare():void { 50 | throw new Error("method must be overridden"); 51 | } 52 | 53 | override public function execute():void { 54 | super.execute(); 55 | } 56 | 57 | protected function executeCommand(mapping:ISubCommandMapping):void { 58 | 59 | var command:ICommand; 60 | 61 | const commandClass:Class = mapping.commandClass; 62 | const payloads:Array = mapping.payloads; 63 | const hasPayloads:Boolean = payloads.length > 0; 64 | 65 | hasPayloads && mapPayloads(payloads); 66 | 67 | if (mapping.guards.length == 0 || guardsApprove(mapping.guards, injector)) { 68 | command = mapping.getOrCreateCommandInstance(injector); 69 | 70 | if (mapping.hooks.length > 0) { 71 | injector.map(commandClass).toValue(command); 72 | applyHooks(mapping.hooks, injector); 73 | injector.unmap(commandClass); 74 | } 75 | } 76 | 77 | hasPayloads && unmapPayloads(payloads); 78 | 79 | if (command && mapping.executeMethod) { 80 | const isAsync:Boolean = command is IAsyncCommand; 81 | isAsync && IAsyncCommand(command).registerCompleteCallback(commandCompleteHandler); 82 | const executeMethod:Function = command[mapping.executeMethod]; 83 | executeMethod(); 84 | isAsync || commandCompleteHandler(true); 85 | } else { 86 | commandCompleteHandler(true); 87 | } 88 | } 89 | 90 | protected function mapPayloads(payloads:Array):void { 91 | for each (var payload:SubCommandPayload in payloads) { 92 | injector.map(payload.type, payload.name).toValue(payload.data); 93 | } 94 | } 95 | 96 | protected function unmapPayloads(payloads:Array):void { 97 | for each (var payload:SubCommandPayload in payloads) { 98 | injector.unmap(payload.type, payload.name); 99 | } 100 | } 101 | 102 | protected function commandCompleteHandler(success:Boolean):void { 103 | throw new Error("method must be overridden"); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/test/actionscript/eu/alebianco/robotlegs/utils/PayloadsTest.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Alessandro Bianco 3 | * Website: http://alessandrobianco.eu 4 | * Twitter: @alebianco 5 | * Created: 13/04/13 11.46 6 | * 7 | * Copyright © 2013 Alessandro Bianco 8 | */ 9 | package eu.alebianco.robotlegs.utils { 10 | import eu.alebianco.robotlegs.utils.support.MacroWithXMLPayload; 11 | import eu.alebianco.robotlegs.utils.support.TestIntCommand; 12 | import eu.alebianco.robotlegs.utils.support.TestStringCommand; 13 | import eu.alebianco.robotlegs.utils.support.MacroWithNamedPayload; 14 | import eu.alebianco.robotlegs.utils.support.MacroWithNumberPayload; 15 | import eu.alebianco.robotlegs.utils.support.MacroWithPseudoNullPayload; 16 | import eu.alebianco.robotlegs.utils.support.MacroWithSimplePayload; 17 | import eu.alebianco.robotlegs.utils.support.TestNameStringCommand; 18 | import eu.alebianco.robotlegs.utils.support.TestNumberCommand; 19 | import eu.alebianco.robotlegs.utils.support.TestXMLCommand; 20 | import eu.alebianco.robotlegs.utils.support.TestXMLListCommand; 21 | 22 | import flash.events.Event; 23 | import flash.events.EventDispatcher; 24 | import flash.events.IEventDispatcher; 25 | 26 | import org.hamcrest.assertThat; 27 | import org.hamcrest.collection.array; 28 | 29 | import robotlegs.bender.extensions.commandCenter.api.ICommandMapping; 30 | import robotlegs.bender.extensions.eventCommandMap.api.IEventCommandMap; 31 | import robotlegs.bender.extensions.eventCommandMap.impl.EventCommandMap; 32 | import robotlegs.bender.framework.api.IContext; 33 | import robotlegs.bender.framework.api.IInjector; 34 | import robotlegs.bender.framework.impl.Context; 35 | import robotlegs.bender.framework.impl.RobotlegsInjector; 36 | 37 | public class PayloadsTest { 38 | 39 | private var injector:IInjector; 40 | private var mappings:Vector.; 41 | private var dispatcher:IEventDispatcher; 42 | private var subject:IEventCommandMap; 43 | private var reported:Array; 44 | 45 | private function reportingFunction(item:Object):void { 46 | reported.push(item); 47 | } 48 | 49 | [Before] 50 | public function before():void { 51 | reported = []; 52 | injector = new RobotlegsInjector(); 53 | const context:IContext = new Context(); 54 | injector = context.injector; 55 | injector.map(Function, "reportingFunction").toValue(reportingFunction); 56 | dispatcher = new EventDispatcher(); 57 | subject = new EventCommandMap(context, dispatcher); 58 | } 59 | 60 | [After] 61 | public function after():void { 62 | injector = null; 63 | } 64 | 65 | [Test] 66 | public function payload_instances_are_mapped():void { 67 | subject.map("trigger", Event).toCommand(MacroWithNamedPayload); 68 | const event:Event = new Event("trigger"); 69 | dispatcher.dispatchEvent(event); 70 | assertThat(reported, array(MacroWithNamedPayload, TestNameStringCommand, "world")); 71 | } 72 | 73 | [Test] 74 | public function simple_values_are_mapped_as_payloads():void { 75 | subject.map("trigger", Event).toCommand(MacroWithSimplePayload); 76 | const event:Event = new Event("trigger"); 77 | dispatcher.dispatchEvent(event); 78 | assertThat(reported, array(MacroWithSimplePayload, TestStringCommand, "world")); 79 | } 80 | 81 | [Test] 82 | public function number_values_are_mapped_as_payloads():void { 83 | subject.map("trigger", Event).toCommand(MacroWithNumberPayload); 84 | const event:Event = new Event("trigger"); 85 | dispatcher.dispatchEvent(event); 86 | assertThat(reported, array(MacroWithNumberPayload, TestNumberCommand, Math.PI)); 87 | } 88 | 89 | [Test] 90 | public function pseudo_null_values_are_mapped_as_payloads():void { 91 | subject.map("trigger", Event).toCommand(MacroWithPseudoNullPayload); 92 | const event:Event = new Event("trigger"); 93 | dispatcher.dispatchEvent(event); 94 | assertThat(reported, array(MacroWithPseudoNullPayload, TestStringCommand, "", TestIntCommand, 0, TestNumberCommand, NaN)); 95 | } 96 | 97 | [Test] 98 | public function xml_values_as_payloads():void { 99 | subject.map("trigger", Event).toCommand(MacroWithXMLPayload); 100 | const event:Event = new Event("trigger"); 101 | dispatcher.dispatchEvent(event); 102 | assertThat(reported, array(MacroWithXMLPayload, TestXMLCommand, "color", TestXMLListCommand, 7)); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Macrobot 2 | 3 | ♥ [Macrobot](https://github.com/alebianco/robotlegs-utilities-macrobot) and want to get involved? 4 | Thanks! There are plenty of ways you can help! 5 | 6 | 7 | ## Bugs 8 | 9 | A bug is a _demonstrable problem_ that is caused by the code in the 10 | repository. Good bug reports are extremely helpful - thank you! 11 | 12 | Guidelines for bug reports: 13 | 14 | 1. **Use the GitHub issue search** — check if the issue has already been 15 | reported. 16 | 17 | 2. **Check if the issue has been fixed** — try to reproduce it using the 18 | latest `master` branch in the repository. 19 | 20 | 3. **Isolate the problem** — ideally create a reduced test 21 | case and a live example. 22 | 23 | A good bug report shouldn't leave others needing to chase you up for more 24 | information. Please try to be as detailed as possible in your report. What is 25 | your environment? What steps will reproduce the issue? What Platform(s) and OS 26 | experience the problem? What would you expect to be the outcome? All these 27 | details will help me to fix any potential bugs. 28 | 29 | Example: 30 | 31 | > Short and descriptive example bug report title 32 | > 33 | > A summary of the issue and the platform/OS environment in which it occurs. If 34 | > suitable, include the steps required to reproduce the bug. 35 | > 36 | > 1. This is the first step 37 | > 2. This is the second step 38 | > 3. Further steps, etc. 39 | > 40 | > `` (a link to the reduced test case) 41 | > 42 | > Any other information you want to share that is relevant to the issue being 43 | > reported. This might include the lines of code that you have identified as 44 | > causing the bug, and potential solutions (and your opinions on their 45 | > merits). 46 | 47 | **[File a bug report](https://github.com/alebianco/robotlegs-utilities-macrobot/issues/)** 48 | 49 | 50 | ## Pull requests 51 | 52 | Good pull requests - patches, improvements, new features - are a fantastic 53 | help. They should remain focused in scope and avoid containing unrelated 54 | commits. If your contribution involves a significant amount of work or substantial 55 | changes to any part of the project, please open an issue to discuss it first. 56 | 57 | Make sure to adhere to the coding conventions used throughout a project 58 | (indentation, accurate comments, etc.). Please update any documentation that is 59 | relevant to the change you're making. 60 | 61 | Please follow this process; it's the best way to get your work included in the 62 | project: 63 | 64 | 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, 65 | and configure the remotes: 66 | 67 | ```bash 68 | # Clones your fork of the repo into the current directory in terminal 69 | git clone https://github.com//robotlegs-utilities-macrobot.git 70 | # Navigate to the newly cloned directory 71 | cd robotlegs-utilities-macrobot 72 | # Assigns the original repo to a remote called "upstream" 73 | git remote add upstream https://github.com/alebianco/robotlegs-utilities-macrobot.git 74 | ``` 75 | 76 | 2. If you cloned a while ago, get the latest changes from upstream: 77 | 78 | ```bash 79 | git checkout master 80 | git pull upstream master 81 | ``` 82 | 83 | 3. Create a new topic branch to contain your feature, change, or fix: 84 | 85 | ```bash 86 | git checkout -b 87 | ``` 88 | 89 | 4. Commit your changes in logical chunks. Please adhere to these [git commit 90 | message 91 | guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) 92 | or your pull request is unlikely be merged into the main project. Use git's 93 | [interactive rebase](https://help.github.com/articles/interactive-rebase) 94 | feature to tidy up your commits before making them public. 95 | 96 | 5. Locally merge (or rebase) the upstream development branch into your topic branch: 97 | 98 | ```bash 99 | git pull [--rebase] upstream master 100 | ``` 101 | 102 | 6. Push your topic branch up to your fork: 103 | 104 | ```bash 105 | git push origin 106 | ``` 107 | 108 | 10. [Open a Pull Request](https://help.github.com/articles/using-pull-requests) with a 109 | clear title and description. 110 | 111 | 112 | ## Do not… 113 | 114 | Please **do not** use the issue tracker for personal support requests. 115 | Please **do not** derail or troll issues. Keep the 116 | discussion on topic and respect the opinions of others. 117 | 118 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Macrobot 2 | 3 | [![Build Status](https://travis-ci.org/alebianco/robotlegs-utilities-macrobot.svg?branch=master)](https://travis-ci.org/alebianco/robotlegs-utilities-macrobot) 4 | 5 | Macro command utility for Robotlegs which provides the ability to execute batches of commands in sequential or parallel fashion. 6 | 7 | **NOTE** This project is a shameful port of the awesome work that [Aaronius](https://github.com/Aaronius) made for the first release of [Robotlegs](http://www.robotlegs.org/). 8 | 9 | ## Introduction 10 | 11 | While using Robotlegs and encapsulating your business logic inside commands, you may find yourself in a situation where you wish to batch commands, instead of relying on events to trigger every step. 12 | Macrobot simplifies this process and provide two way to group commands: 13 | 14 | **Sequence**: The commands will be executed in order one after the other. A command will not be executed until the previous one is complete. The macro itself will not be complete until all its commands are complete. 15 | 16 | **Parallel**: The commands will be executed as quickly as possible, with no regards on the order in which they were registered. The macro itself will not be complete until all its commands are complete. 17 | 18 | # Releases 19 | 20 | You'll find new versions of the extension in the [Releases page](https://github.com/alebianco/robotlegs-utilities-macrobot/releases) of the repository. 21 | 22 | ## Usage 23 | 24 | To create a macro command, extend on the two classes Macrobot provides: `ParallelMacro` or `SequenceMacro`. 25 | Override the prepare() method and add sub commands by calling `addSubCommand()` specifying the command class to use. 26 | At the appropriate time the command will be created, initiated by satisfying the injection points and then executed. 27 | This automated process of instantiation, injection, and execution is very similar to how commands are normally prepared and executed in Robotlegs. 28 | You could use _Guards_ and _Hooks_ as you would normally use with regular commands to control the execution workflow. 29 | Additionally you could use the `withPayloads()` method to add some data that can be used to satisfy the injection points of the sub commands. The data provided will be available to the guards and hooks applied to the sub command as well. 30 | 31 | Here's an example of a simple sequential macro: 32 | ```ActionScript 33 | public class MyMacro extends SequenceMacro { 34 | override public function prepare() { 35 | add(CommandA); 36 | add(CommandB); 37 | add(CommandC); 38 | } 39 | } 40 | ``` 41 | 42 | ### Using Guards 43 | 44 | Guards are used to approve or deny the execution of one of the subcommands. 45 | 46 | ```ActionScript 47 | public class DailyRoutine extends SequenceMacro { 48 | override public function prepare() { 49 | add(Work); 50 | add(Party).withGuards(IsFriday); // It will only party on fridays 51 | add(Sleep); 52 | } 53 | } 54 | 55 | public class IsFriday implements IGuard { 56 | public funciton approve():Boolean { 57 | return new Date().day == 5; 58 | } 59 | } 60 | ``` 61 | Refer to the [Robotlegs documentation](https://github.com/robotlegs/robotlegs-framework/blob/master/src/robotlegs/bender/framework/readme-guards.md) for more details about Guards. 62 | 63 | ### Using Hooks 64 | 65 | Hooks run before the subcommands. They are typically used to run custom actions based on environmental conditions. 66 | Hooks will run only if the applied Guards approve the execution of the command. 67 | 68 | ```ActionScript 69 | public class DailyRoutine extends SequenceMacro { 70 | override public function prepare() { 71 | add(Work); 72 | add(Party).withGuards(IsFriday); // It will only party on fridays 73 | add(Sleep).withHook(GoToHome); // Try to avoid sleeping at the office or the pub 74 | } 75 | } 76 | 77 | public class IsFriday implements IHook { 78 | [Inject] public var me:Person; 79 | public funciton hook():void { 80 | me.goHome(); 81 | } 82 | } 83 | ``` 84 | Refer to the [Robotlegs documentation](https://github.com/robotlegs/robotlegs-framework/blob/master/src/robotlegs/bender/framework/readme-hooks.md) for more details about Hooks. 85 | 86 | 87 | ### Using Payloads 88 | 89 | Payloads are used to temporary inject some data, which would not be available otherwise, and make it available to the subcommand, it's guards and it's hooks. 90 | 91 | You can use pass the data to be injected directly to the `withPayloads()` method, for a normal injection. 92 | ```ActionScript 93 | public class Macro extends SequenceMacro { 94 | override public function prepare() { 95 | const data:SomeModel = new SomeModel() 96 | add(Action).withPayloads(data); 97 | } 98 | } 99 | 100 | public class Action implements ICommand { 101 | [Inject] public var data:SomeModel; 102 | public function execute():void { 103 | data.property = 'value' 104 | } 105 | } 106 | ``` 107 | 108 | Or you can use the `SubCommandPayload` class to create a more complex injection. 109 | ```ActionScript 110 | public class Macro extends SequenceMacro { 111 | override public function prepare() { 112 | const data:SomeModel = new SomeModel() 113 | const payload:SubCommandPayload = new SubCommandPayload(data).withName('mydata').ofClass(IModel) 114 | add(Action).withPayloads(payload); 115 | } 116 | } 117 | 118 | public class Action implements ICommand { 119 | [Inject(name='mydata')] public var data:IModel; 120 | public function execute():void { 121 | data.property = 'value' 122 | } 123 | } 124 | ``` 125 | 126 | ### Asynchronous commands 127 | 128 | While Macrobot can work with synchronous commands, it is most effective when you have to deal with asynchronous ones. 129 | Your sub command may wait for a response from a server or for user interaction before being marked as complete. 130 | In this case you command can subclass Macrobot's AsyncCommand and call `dispatchComplete()` when it should be marked as complete. 131 | `dispatchComplete()` receives a single parameter which reports whether the subcommand completed successfully. 132 | 133 | Here's an example of a simulated asynchronous sub command: 134 | ```ActionScript 135 | public class DelayCommand extends AsyncCommand { 136 | protected var timer:Timer; 137 | override public function execute():void { 138 | super.execute(); 139 | timer = new Timer(1000, 1); 140 | timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerCompleteHandler); 141 | timer.start(); 142 | } 143 | protected function timerCompleteHandler(event:TimerEvent):void { 144 | timer.removeEventListener(TimerEvent.TIMER_COMPLETE, timerCompleteHandler); 145 | timer = null; 146 | dispatchComplete(true); 147 | } 148 | } 149 | 150 | public class MyMacro extends SequenceMacro { 151 | override public function prepare():void { 152 | add(DelayCommand) 153 | add(OtherCommand) 154 | registerCompleteCallback(onComplete) 155 | } 156 | protected function onComplete(success):void { 157 | trace('all commands have been executed') 158 | } 159 | } 160 | ``` 161 | 162 | ### Atomic execution 163 | 164 | For sequential macros, when the_ atomic_ property is set to **false** (it is **true** by default) and one of the sub commands dispatches a failure (using `dispatchComplete(false)`), subsequent sub commands will not be executed and the macro itself will dispatch failure. 165 | 166 | This behaviour does not apply to parallel commands. 167 | 168 | ## Building 169 | 170 | In the **gradle** folder, make a copy of the _user.properties.eg_ file and call it _user.properties_ 171 | Edit that file to provide values specific to your system 172 | Use the `gradlew` script to build the project 173 | 174 | ## Contributing 175 | 176 | If you want to contribute to the project refer to the [contributing document](CONTRIBUTING.md) for guidelines. 177 | --------------------------------------------------------------------------------