You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2019/09/22 06:01:49 UTC
[royale-asjs] 04/09: Add support for command pattern to Crux.
This is an automated email from the ASF dual-hosted git repository.
gregdove pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
commit f555f1c6ca02b48ec771302707585ed843c60847
Author: greg-dove <gr...@gmail.com>
AuthorDate: Sun Sep 22 09:36:30 2019 +1200
Add support for command pattern to Crux.
---
.../projects/Crux/src/main/royale/CruxClasses.as | 3 +
.../royale/org/apache/royale/crux/BeanFactory.as | 8 +-
.../royale/crux/metadata/InjectMetadataTag.as | 1 +
.../royale/crux/processors/InjectProcessor.as | 2 +-
.../royale/crux/utils/commands/CommandMap.as | 216 +++++++++++++++++++++
.../apache/royale/crux/utils/commands/ICommand.as | 27 +++
.../crux/utils/commands/IEventAwareCommand.as | 30 +++
7 files changed, 282 insertions(+), 5 deletions(-)
diff --git a/frameworks/projects/Crux/src/main/royale/CruxClasses.as b/frameworks/projects/Crux/src/main/royale/CruxClasses.as
index 6516885..705fa3b 100644
--- a/frameworks/projects/Crux/src/main/royale/CruxClasses.as
+++ b/frameworks/projects/Crux/src/main/royale/CruxClasses.as
@@ -48,6 +48,7 @@ package
import org.apache.royale.crux.ISetUpValidator; ISetUpValidator;
import org.apache.royale.crux.ITearDownValidator; ITearDownValidator;
import org.apache.royale.crux.Prototype; Prototype;
+
@@ -108,6 +109,8 @@ package
import org.apache.royale.crux.utils.async.AsyncTokenOperation; AsyncTokenOperation;
import org.apache.royale.crux.utils.async.IAsynchronousEvent; IAsynchronousEvent;
import org.apache.royale.crux.utils.async.IAsynchronousOperation; IAsynchronousOperation;
+
+ import org.apache.royale.crux.utils.commands.CommandMap; CommandMap;
import org.apache.royale.crux.utils.chain.AbstractChain; AbstractChain;
import org.apache.royale.crux.utils.chain.AsyncCommandChainStep; AsyncCommandChainStep;
diff --git a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/BeanFactory.as b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/BeanFactory.as
index ccceea2..4c731a8 100644
--- a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/BeanFactory.as
+++ b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/BeanFactory.as
@@ -110,7 +110,7 @@ package org.apache.royale.crux
if( waitForSetup )
return;
- trace("BeanFactory completing setup");
+ //trace("BeanFactory completing setup");
// bean setup has to be delayed until after all startup beans have been added
for each(var bean:Bean in beans)
@@ -352,7 +352,7 @@ package org.apache.royale.crux
if( bean.initialized )
return;
- trace("BeanFactory::setUpBean", bean);
+ //trace("BeanFactory::setUpBean", bean);
bean.initialized = true;
var processor:IProcessor;
@@ -366,7 +366,7 @@ package org.apache.royale.crux
// Handle Metadata Processors
if(processor is IMetadataProcessor)
{
- trace("processor is IMetadataProcessor");
+ //trace("processor is IMetadataProcessor");
var metadataProcessor:IMetadataProcessor = IMetadataProcessor( processor );
// get the tags this processor is interested in
@@ -382,7 +382,7 @@ package org.apache.royale.crux
// Handle Bean Processors
if(processor is IBeanProcessor)
{
- trace("processor is IBeanProcessor");
+ //trace("processor is IBeanProcessor");
IBeanProcessor(processor).setUpBean(bean);
}
}
diff --git a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/metadata/InjectMetadataTag.as b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/metadata/InjectMetadataTag.as
index d746b52..5843045 100644
--- a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/metadata/InjectMetadataTag.as
+++ b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/metadata/InjectMetadataTag.as
@@ -136,6 +136,7 @@ package org.apache.royale.crux.metadata
{
super.copyFrom( metadataTag );
+ //@todo consider removing the 'bean' arg support or putting it only in debug-only build
if( hasArg( "bean" ) && hasArg( "source" ) )
throw new Error( "Your metadata tag defines both a bean and source attribute. source has replaced bean, please update accordingly." );
diff --git a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/processors/InjectProcessor.as b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/processors/InjectProcessor.as
index 163e527..d3d130f 100644
--- a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/processors/InjectProcessor.as
+++ b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/processors/InjectProcessor.as
@@ -412,7 +412,7 @@ package org.apache.royale.crux.processors
}
catch( error:ReferenceError )
{
- trace('todo')
+ trace('todo ReferenceError caught', error)
}
}
diff --git a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/CommandMap.as b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/CommandMap.as
new file mode 100644
index 0000000..05913d9
--- /dev/null
+++ b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/CommandMap.as
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2010 Swiz Framework Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.royale.crux.utils.commands
+{
+ import org.apache.royale.events.Event;
+
+ import org.apache.royale.crux.Bean;
+ import org.apache.royale.crux.ICrux;
+ import org.apache.royale.crux.ICruxAware;
+ import org.apache.royale.crux.Prototype;
+ import org.apache.royale.crux.reflection.TypeCache;
+
+
+ /**
+ * Class used to map events to the commands they should trigger.
+ */
+ public class CommandMap implements ICruxAware
+ {
+ // ========================================
+ // protected properties
+ // ========================================
+
+ /**
+ * Backing variable for crux setter.
+ */
+ protected var _crux:ICrux;
+
+ /**
+ * Object hash to hold mappings (only string keys needed).
+ */
+ protected var map:Object = {};
+
+
+ // ========================================
+ // public properties
+ // ========================================
+
+ /**
+ * Setter to satisfy ICruxAware interface contract.
+ *
+ * @see org.apache.royale.crux.core.ICruxAware
+ */
+ public function set crux( crux:ICrux ):void
+ {
+ // if crux is null, we are being torn down
+ if( crux )
+ {
+ _crux = crux;
+ mapCommands();
+ }
+ else
+ {
+ unmapCommands();
+ _crux = crux;
+ }
+ }
+
+ // ========================================
+ // protected methods
+ // ========================================
+
+ /**
+ * Handler method triggered when a mapped event is caught.
+ */
+ protected function handleCommandEvent( event:Event ):void
+ {
+ // make sure we have a mapping
+ if( map[ event.type ] != null )
+ {
+ var indexesToClear:Array = [];
+ var mappings:Array = map[ event.type ] as Array;
+
+ for( var i:int = 0; i < mappings.length; i++ )
+ {
+ // retrieve mapping
+ var commandMapping:CommandMapping = CommandMapping( mappings[ i ] );
+
+ // validate event class
+ if( !( event is commandMapping.eventClass ) )
+ continue;
+
+ // get our command bean
+ var commandPrototype:Bean = _crux.beanFactory.getBeanByType( commandMapping.commandClass );
+
+ if( commandPrototype == null )
+ throw new Error( "Command bean not found for mapped event type." );
+
+ if( commandPrototype is Prototype )
+ {
+ // get a new instance of the command class
+ var command:Object = Prototype( commandPrototype ).source;
+
+ if( !( command is ICommand ) )
+ throw new Error( "Commands must implement org.apache.royale.crux.utils.commands.ICommand." );
+
+ // provide event reference if command is IEventAwareCommand
+ if( command is IEventAwareCommand )
+ IEventAwareCommand( command ).event = event;
+
+ ICommand( command ).execute();
+ }
+ else
+ {
+ throw new Error( "Commands must be provided as Prototype beans." );
+ }
+
+ if( commandMapping.oneTime )
+ indexesToClear.push( i );
+ }
+
+ if( indexesToClear.length > 0 )
+ {
+ for( var j:int = indexesToClear.length - 1; j > -1; j-- )
+ {
+ mappings.splice( indexesToClear[ j ], 1 );
+ }
+
+ // if no more commands are mapped to this event type, remove from map
+ if( mappings.length == 0 )
+ delete map[ event.type ];
+ }
+ }
+ }
+
+ /**
+ * Abstract method that sub classes should override and populate with calls to <code>mapCommand()</code>.
+ * Mapping commands here (and letting it be called for you) ensures all the necessary pieces have
+ * been provided before attempting to create any mappings.
+ */
+ protected function mapCommands():void
+ {
+ // do nothing, subclasses must override
+ }
+
+ /**
+ * Method that performs actual event to command mapping.
+ */
+ protected function mapCommand( eventType:String, commandClass:Class, eventClass:Class = null, oneTime:Boolean = false ):void
+ {
+ if( map[ eventType ] == null )
+ {
+ map[ eventType ] = [ new CommandMapping( eventType, commandClass, eventClass, oneTime ) ];
+ }
+ else
+ {
+ var mappings:Array = map[ eventType ] as Array;
+
+ for each( var cm:CommandMapping in mappings )
+ {
+ if( cm.commandClass == commandClass )
+ throw new Error( cm.commandClass + " already mapped to " + eventType );
+ }
+
+ mappings.push( new CommandMapping( eventType, commandClass, eventClass, oneTime ) );
+ }
+
+ // create Prototype bean for commandClass if it hasn't been created already
+ if( _crux.beanFactory.getBeanByType( commandClass ) == null )
+ {
+ // create a Prototype for adding to the BeanFactory
+ var commandPrototype:Prototype = new Prototype( commandClass );
+ commandPrototype.typeDescriptor = TypeCache.getTypeDescriptor( commandClass/*, _crux.domain*/ );
+ // add command bean for later instantiation
+ _crux.beanFactory.addBean( commandPrototype, false );
+ }
+
+ // listen for event that will trigger this command
+ _crux.dispatcher.addEventListener( eventType, handleCommandEvent );
+ }
+
+ protected function unmapCommands():void
+ {
+ for( var eventType:String in map )
+ {
+ _crux.dispatcher.removeEventListener( eventType, handleCommandEvent );
+
+ delete map[ eventType ];
+ }
+
+ map = null;
+ }
+ }
+}
+import org.apache.royale.events.Event;
+
+/**
+ * Inner class used to hold the details of a mapping.
+ */
+class CommandMapping
+{
+ public var eventType:String;
+ public var commandClass:Class;
+ public var eventClass:Class;
+ public var oneTime:Boolean;
+
+ public function CommandMapping( eventType:String, commandClass:Class, eventClass:Class = null, oneTime:Boolean = false )
+ {
+ this.eventType = eventType;
+ this.commandClass = commandClass;
+ this.eventClass = eventClass || Event;
+ this.oneTime = oneTime;
+ }
+}
diff --git a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/ICommand.as b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/ICommand.as
new file mode 100644
index 0000000..fb07806
--- /dev/null
+++ b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/ICommand.as
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 Swiz Framework Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.royale.crux.utils.commands
+{
+ /**
+ * Base interface that must be implemented in order to be mapped to an event in a CommandMap.
+ *
+ * @see org.apache.royale.crux.utils.commands.CommandMap
+ */
+ public interface ICommand
+ {
+ function execute():void;
+ }
+}
diff --git a/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/IEventAwareCommand.as b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/IEventAwareCommand.as
new file mode 100644
index 0000000..5c1ae17
--- /dev/null
+++ b/frameworks/projects/Crux/src/main/royale/org/apache/royale/crux/utils/commands/IEventAwareCommand.as
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 Swiz Framework Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.royale.crux.utils.commands
+{
+ import org.apache.royale.events.Event;
+
+ /**
+ * Interface that instructs a Crux CommandMap to supply a reference to the event
+ * which triggered this command's execution.
+ *
+ * @see org.apache.royale.crux.utils.commands.CommandMap
+ */
+ public interface IEventAwareCommand extends ICommand
+ {
+ function set event( value:Event ):void;
+ }
+}