LowRA API Documentation Annexes |  All Packages |  All Classes |  Index |  Frames
Customize IoC Assembler  
 

Summary

  1. Overview
  2. Builds custom IoC assembler
  3. Variables substitution
  4. Pre processing methods
  5. Processor

 

Overview

To play with IoC architecture, we have to use a xml context and an ApplicationLoader loader to load, parse, and built everything in context.
LowRA comes with a default system to define this xml context and a default ApplicationLoader instanciation.
This helper is com.bourre.ioc.DefaultApplicationRunner class.
This helper just create a basic ApplicationLoader instance, and starts xml content loading.

Let's show how to build custom IoC runner. ( the famous "assembler.swf" file ).

 

Builds custom IoC assembler

Easy way is to extends the DefaultApplicationRunner class as it implements all needed features, but we can build new one from scratch too.

DefaultApplicationRunner extends Sprite class ( to be a main class ) and implements the ApplicationLoaderListener interface to listen to all IoC steps.
Just override some methods to custom your process, for example :

package com.project.ioc.CustomRunner
{
	import com.bourre.ioc.DefaultApplicationRunner;

	public class CustomRunner extends DefaultApplicationRunner
	{
		override protected function initStage( ) : void
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.SHOW_ALL;
} } }

To customize ApplicationLoader instaniation, just override the #createApplicationLoader() method :
Example, set 'anticache' system to false.

package com.project.ioc.CustomRunner
{
	import com.bourre.ioc.DefaultApplicationRunner;

	public class CustomRunner extends DefaultApplicationRunner
	{
		override protected function createApplicationLoader( ) : ApplicationLoader
{
var loader : ApplicationLoader = new ApplicationLoader( this, false );
oLoader.setAntiCache( false );
oLoader.setDisplayObjectBuilder( new DefaultDisplayObjectBuilder( ) );
oLoader.addListener( this );

return loader;
} } }

You can also add variables substitution, pre processing ( or processor ) actions overriding the #preprocess() method.

package com.project.ioc.CustomRunner
{
	import com.bourre.ioc.DefaultApplicationRunner;

	public class CustomRunner extends DefaultApplicationRunner
	{
		override protected function preprocess( ) : void
{
oLoader.addProcessingMethod( ProcessingHelper.addResource, "newStyle", "myStyle.css" );
oLoader.addProcessor( new AddDefaultDLLProcessor() );
} } }

Just compile this new class like a classic swf file, and use it as main application entry point ( assembler.swf );

 

Variables substitution

ApplicationLoader class allow to replace variables defined in loaded context file.
For example, we want to change the position of a Kairos monitor when context is loaded, using custom value.

First step, make dynamic properties in your context file :

<beans>
<dll url="MonitoringPluginDLL.swf" />

<plugin id="Monitor" type="lowra.plugins.utils.MonitoringPlugin">
<property name="x" value="${POSITION_X}" /> <property name="y" value="${POSITION_Y}" /> <property name="alpha" value="0.5" />
</plugin>
</beans>

Now, we have just to set the new values for these variables before parsing the context file.
Override the #preprocess() method of your IoC runner ( assembler ).

package com.project.ioc.CustomRunner
{
	import com.bourre.ioc.DefaultApplicationRunner;

	public class CustomRunner extends DefaultApplicationRunner
	{
		override protected function preprocess( ) : void
{
oLoader.setVariable( "POSITION_X", 200 );
oLoader.setVariable( "POSITION_Y", 50 );
} } }

When file is loaded and before the IoC parsing, the loader replace the variables name with defined values.

 

Pre Processing

ApplicationLoader allow to apply pre processing actions before starting context parser.
As Variable substitution, pre processing allow to modify the loaded XML data, but here, we don't have to define special variable ( ${XXX} ) in context to change, we can acces all xml content.

To add pre processing action, just use the ApplicationLoader#addProcessingMethod() method. ( or #addProcessor() if you use ContextProcessor implementation ).
This is the signature :

public function addProcessingMethod( processingMethod : Function, ...rest ) : void;

So, we have to pass a method reference first and then optionals parameters.
The passed-in processingMethod has a basic signature like :

function processingMethod( xml : XML ) : XML;

Summary : A processingMethod must return an XML object and wait for an XML object as first argumen (and can wait for optional arguments too ).
Example :

package com.project.ioc.CustomRunner
{
	import com.bourre.ioc.DefaultApplicationRunner;

	public class CustomRunner extends DefaultApplicationRunner
	{
		override protected function preprocess( ) : void
{
oLoader.addProcessingMethod( displayXML, "Processing example" );
} public function displayXML( xml : XML, title : String ) : XML { PixlibDebug.INFO( title ); PixlibDebug.INFO( xml.toXMLString() ); return xml; } } }

As you can see, optionals parameters passed to #addProcessingMethod() method are automatically added when calling the processingMethod.
You can add as many processors you want. XML passed and returns is changed on each processing step.

Let's show a concrete example now.
LowRA comes with an helper class to play with xml context content.
Helper is com.bourre.ioc.context.processor.ProcessingHelper utility class.
Take a look at API Documentation for more information about this helper.

Example of a more complex pre processing :

package com.project.ioc.CustomRunner
{
	import com.bourre.ioc.DefaultApplicationRunner;

	public class CustomRunner extends DefaultApplicationRunner
	{
		override protected function preprocess( ) : void
{
oLoader.addProcessingMethod( ProcessingHelper.changeObjectAttribute, "cross", "visible", "false" );
oLoader.addProcessingMethod( ProcessingHelper.changeObjectAttribute, "cross", "type", "Sprite", true );
oLoader.addProcessingMethod( ProcessingHelper.changePropertyValue, "cross", "x", 600 );
oLoader.addProcessingMethod( ProcessingHelper.changePropertyValue, "cross", "alpha", 0.5 );
oLoader.addProcessingMethod( ProcessingHelper.changeObjectID, "obj", "myNewOBJ" );
oLoader.addProcessingMethod( ProcessingHelper.changeMethodArgumentValue, "cross", "test", 0, "onChange" );
oLoader.addProcessingMethod( ProcessingHelper.changeMethodArgumentValue, "cross", "test", 1, null, "String" );
oLoader.addProcessingMethod( ProcessingHelper.changeMethodArgumentValue, "cross", "test", 2, "44", "int" );
oLoader.addProcessingMethod( ProcessingHelper.changeMethodArgumentValue, "cross", "test", 3, "myNewOBJ" ); oLoader.addProcessingMethod( ProcessingHelper.addDLL, "MyNewDLL.swf" );
oLoader.addProcessingMethod( ProcessingHelper.addResource, "newStyle", "myStyle.css" );
oLoader.addProcessingMethod( ProcessingHelper.addNode, node );
} } }

Node used for addNode() preprocessing example :

var node : XML = <object id='obj2' type='Object'><property name='p4' value='hello4' /></object>;

This is ouput diff between loaded XML and pre processing result :

loaded xml content pre processing result
<beans>
<root id="root">

<avatar id="cross" url="cross.png" visible="true">
<property name="x" value="0" />
<property name="alpha" value="1" />

<method-call name="test"><!-- for example only -->
<argument value="Romain" type="String" />
<argument value="Ecarnot" />
<argument value="31" type="Number" />
<argument ref="obj" />
</method-call>
</avatar>

</root>

<object id="obj" type="Object">
<property name="p1" value="hello1"/>
<property name="p2" value="hello2"/>
</object>

<dictionary id="dico" type="Dictionary">
<item> <key value="o"/> <value ref="obj"/> </item>
</dictionary>
</beans>






<beans>
<root id="root">

<avatar id="cross" url="cross.png" visible="false" type="Sprite">
<property name="x" value="600" />
<property name="alpha" value="0.5" />

<method-call name="test"><!-- for example only -->
<argument value="OnChange" type="String" />
<argument value="Ecarnot" type="String" />
<argument value="44" type="int" />
<argument ref="myNewOBJ" />
</method-call>
</avatar>

</root>

<object id="myNewOBJ" type="Object">
<property name="p1" value="hello1"/>
<property name="p2" value="hello2"/>
</object>

<dictionary id="dico" type="Dictionary">
<item> <key value="o"/> <value ref="myNewOBJ"/> </item>
</dictionary> <dll url="MyNewDLL.swf"/> <rsc id="newStyle" url="myStyle.css"/> <object id="obj2" type="object"> <property name="p4" value="hello4"/> </object>
</beans>

After pre processing, the IoC parser starts his job as normally.

Processor

Instead of using inner function for pre processing ( see Pre processing methods ), LowRA offer ContextProcessor implementations.
Use the ApplicationLoader#addProcessor() to add a new ContextProcessor to pre processing list.

package com.project.ioc.CustomRunner
{
	import com.bourre.ioc.DefaultApplicationRunner;

	public class CustomRunner extends DefaultApplicationRunner
	{
		override protected function preprocess( ) : void
{
oLoader.addProcessor( new AddDefaultDLLProcessor() );
} } }

AddDefaultDLLProcessor implementation sample :

package com.ioc.processors
{
	import com.bourre.ioc.context.processor.ContextProcessor;

	public class AddDefaultDLLProcessor implements ContextProcessor
	{
		public function process( xml : XML ) : XML
		{
			xml.appendChild( _getDLLNode( "DimensionDLL.swf" ) );
xml.appendChild( _getDLLNode( "RangeDLL.swf" ) ); xml.appendChild( _getDLLNode( "XMLToObjectDeserializerDLL.swf" ) );
return xml; } private function _getDLLNode( url : String ) : XML { var dll : XML = <{ContextNodeNameList.DLL} />;
dll.@[ContextAttributeList.URL] = url; return dll; } } }