<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"
>

<channel>
	<title>Building Blocks &#187; AIR</title>
	<atom:link href="http://joelhooks.com/category/air/feed/" rel="self" type="application/rss+xml" />
	<link>http://joelhooks.com</link>
	<description>If it feels like magic, there's probably a trick. - rands</description>
	<lastBuildDate>Tue, 29 Jun 2010 18:45:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
		<item>
		<title>Piping the Machine: PureMVC Multicore with Pipes and the Finite State Machine (FSM)</title>
		<link>http://joelhooks.com/2009/05/18/piping-the-machine-puremvc-multicore-with-pipes-and-the-finite-state-machine-fsm/</link>
		<comments>http://joelhooks.com/2009/05/18/piping-the-machine-puremvc-multicore-with-pipes-and-the-finite-state-machine-fsm/#comments</comments>
		<pubDate>Mon, 18 May 2009 20:19:43 +0000</pubDate>
		<dc:creator>Joel</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[puremvc]]></category>
		<category><![CDATA[pyAMF]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[software architecture]]></category>

		<guid isPermaLink="false">http://joelhooks.com/?p=177</guid>
		<description><![CDATA[This is going to be a walkthrough of making use of PureMVC Multicore (AS3). To help in building a PureMVC Multicore application, we are going to make use of the StateMachine utility for initial setup and configuration as well as the Pipes utility for communication between cores. Here's the Source. 
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_PipingTheMachine_1792816625"
			class="flashmovie"
			width="400"
			height="300">
	<param name="movie" value="/examples/pipemachine/PipingTheMachine.swf" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="/examples/pipemachine/PipingTheMachine.swf"
			name="fm_PipingTheMachine_1792816625"
			width="400"
			height="300">
	<!--<![endif]-->
		]]></description>
			<content:encoded><![CDATA[<p>This is going to be a walkthrough of making use of PureMVC Multicore (AS3). To help in building a PureMVC Multicore application, we are going to make use of the StateMachine utility for initial setup and configuration as well as the Pipes utility for communication between cores.</p>
<p><a href="http://joelhooks.com/examples/pipemachine/srcview/">Here's the Source.</a></p>
<p style="text-align: center;">[kml_flashembed fversion="9.0.124" movie="/examples/pipemachine/PipingTheMachine.swf" targetclass="flashmovie" useexpressinstall="true" publishmethod="static" width="450" height="500"]<a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object><br />
<span id="more-177"></span></p>
<h2>Overview</h2>
<p>PureMVC can seem a bit overwhelming at first, but once the core concepts are understood the simplicity of the framework is possibly its biggest strength. Developing multicore applications in PureMVC, that is applications that create multiple instances of the PureMVC core actors (Facade, Model, View, Controller), adds another level of complexity that can be daunting. Luckily, there are utilities to help us out here, and abstract some of the problems with communication between modules loaded into an application.</p>
<p>This tutorial is based on the <a href="http://www.seaofarrows.com" target="_blank">Sea of Arrows player</a> put together by Cliff Hall. My goal was to remove some of the complexity involved with a real application and deconstruct the blocks used to build the player in a form that is easier to digest. It is highly recommended that you check out the player for a further example of this particular application structure.</p>
<p>For the purposes of demonstration this application is kept as simple as possible. For a trivial project, this level of complexity in regards to multiple cores, dynamically loaded modules, a finite state machine, and a plumbed framework for components to communicate is over-engineered (at best). It seems like a lot of work, and it is, but the payoff is when you have a complex project with multiple developers and designers working across many modules. This structure is made to scale, and scale well providing many options for efficient development. It allows for finely grained control of all of the actors in your system.</p>
<h2>The Tools</h2>
<p>Here is a brief overview of the tools we are going to use, and then we will get into some code and look at a simple example of everything put together.</p>
<h3>PureMVC</h3>
<p style="text-align: center;"><img class="aligncenter" src="http://puremvc.org/images/stories/puremvc-icon.jpg" alt="" width="318" height="200" /></p>
<p><em>From the website:</em></p>
<blockquote><p><a href="http://puremvc.org/content/view/67/178/" target="_blank">PureMVC is a lightweight framework</a> for creating applications based upon the classic Model, View and Controller concept.</p>
<p>Based upon proven design patterns, this free, open source framework which was originally implemented in the ActionScript 3 language for use with Adobe Flex, Flash and AIR, is now being ported to all major development platforms.</p></blockquote>
<p>If you want a tutorial for basic PureMVC usage, <a href="http://flash.tutsplus.com/tutorials/workflow/understanding-the-puremvc-open-source-framework/">click here</a>.</p>
<h3>Pipes</h3>
<p><a href="http://trac.puremvc.org/Utility_AS3_MultiCore_Pipes">Pipes</a> is a drop in utility for <a href="http://trac.puremvc.org/PureMVC_AS3_MultiCore">multicore PureMVC</a> applications that utilizes a plumbing metaphor to facilitate communication between cores. If you've ever walked down the PVC aisle of your local mega-hardware store, you are familiar with the objects represented in the utility.</p>
<p style="text-align: center;"><img class="size-full wp-image-187  aligncenter" title="pipes-diagram" src="http://69.164.207.135/wp-content/uploads/2009/05/pipes-diagram.png" alt="pipes-diagram" width="500" height="208" /></p>
<p style="text-align: left;">The above diagram comes from the excellent <a href="http://www.joshuaostrom.com/2008/06/15/understanding-puremvc-pipes/">Pipes overview written by Joshua Ostrom</a>.</p>
<h3>StateMachine</h3>
<p>The <a href="http://trac.puremvc.org/Utility_AS3_StateMachine">StateMachine utility</a> is a <a href="http://en.wikipedia.org/wiki/Finite_state_machine">finite state machine</a> for controlling application state in PureMVC. Configured by XML it seems daunting at first, but is relatively simple with only a handful of classes in the utility to make things happen. It makes for an elegant way to step through logical progressions and control available actions inside your application. This example is utilizing the StateMachine for the initial configuration, but it is possible to create complex workflows with the utility.</p>
<p>Check out the <a href="http://code.google.com/p/puremvc-utilities/">FSMVisualizer</a> for a really cool way to look at the PureMVC StateMachine.</p>
<h2>The Code</h2>
<h3>The Shell</h3>
<p>The shell of the application is the root container that will be in charge of creating instances of the modules and displaying their visual components. In this Flex example of the shell, the main MXML file serves as the viewComponent of the first PureMVC core that will be created.</p>
<p>The application is started like a typical PureMVC application. The difference here is with the naming convention being used. Normally in an application that will make use of a single PureMVC core will will create an ApplicationFacade. In this multicore application we are going to instead name the facade <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/ShellFacade.as.html">ShellFacade</a>.</p>
<p>The <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/ShellFacade.as.html">ShellFacade</a> class contains our notification constants. In this case it also cotains constants related to the StateMachine utility that define the states, their actions, and the notifications associated with those actions.</p>
<p>The StateMachine is initialized in our <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/controller/StartupCommand.as.html">StartupCommand</a>, which is a typical MacroCommand found in most PureMVC applications. The first Command run is the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/controller/state/InjectFSMCommand.as.html">InjectFSMCommand</a> which initializes the StateMachine and provides it with the XML configuration defining the various states. The next Command issued is the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/controller/state/StartShellCommand.as.html">StartShellCommand</a>, which is our initial state as configured by the StateMachine.</p>

<div class="wp_codebox"><table><tr id="p1772"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="code" id="p177code2"><pre class="xml" style="font-family:monospace;">var fsm:XML =
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fsm</span> <span style="color: #000066;">initial</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.STARTING<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
	<span style="color: #808080; font-style: italic;">&lt;!-- STARTUP THE SHELL --&gt;</span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;state</span> <span style="color: #000066;">name</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.STARTING<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;transition</span> <span style="color: #000066;">action</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.STARTED<span style="color: #66cc66;">&#125;</span></span>
<span style="color: #009900;">       			   <span style="color: #000066;">target</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.PLUMBING<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;transition</span> <span style="color: #000066;">action</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.STARTUP_FAILED<span style="color: #66cc66;">&#125;</span></span>
<span style="color: #009900;">       			   <span style="color: #000066;">target</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.FAILING<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/state<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
	<span style="color: #808080; font-style: italic;">&lt;!-- PLUMB THE CORES --&gt;</span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;state</span> <span style="color: #000066;">name</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.PLUMBING<span style="color: #66cc66;">&#125;</span> <span style="color: #000066;">changed</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.PLUMB<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;transition</span> <span style="color: #000066;">action</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.PLUMBED<span style="color: #66cc66;">&#125;</span></span>
<span style="color: #009900;">       			   <span style="color: #000066;">target</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.ASSEMBLING<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;transition</span> <span style="color: #000066;">action</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.PLUMB_FAILED<span style="color: #66cc66;">&#125;</span></span>
<span style="color: #009900;">       			   <span style="color: #000066;">target</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.FAILING<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/state<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
	<span style="color: #808080; font-style: italic;">&lt;!-- ASSEMBLE THE VIEW --&gt;</span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;state</span> <span style="color: #000066;">name</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.ASSEMBLING<span style="color: #66cc66;">&#125;</span> <span style="color: #000066;">changed</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.ASSEMBLE<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;transition</span> <span style="color: #000066;">action</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.ASSEMBLED<span style="color: #66cc66;">&#125;</span></span>
<span style="color: #009900;">       			   <span style="color: #000066;">target</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.NAVIGATING<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;transition</span> <span style="color: #000066;">action</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.ASSEMBLY_FAILED<span style="color: #66cc66;">&#125;</span></span>
<span style="color: #009900;">       			   <span style="color: #000066;">target</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.FAILING<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/state<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
	<span style="color: #808080; font-style: italic;">&lt;!-- READY TO ACCEPT BROWSER OR USER NAVIGATION --&gt;</span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;state</span> <span style="color: #000066;">name</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.NAVIGATING<span style="color: #66cc66;">&#125;</span> <span style="color: #000066;">changed</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.NAVIGATE<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
	<span style="color: #808080; font-style: italic;">&lt;!-- REPORT FAILURE FROM ANY STATE --&gt;</span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;state</span> <span style="color: #000066;">name</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.FAILING<span style="color: #66cc66;">&#125;</span> <span style="color: #000066;">changed</span>=<span style="color: #66cc66;">&#123;</span>ShellFacade.FAIL<span style="color: #66cc66;">&#125;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fsm<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>;</pre></td></tr></table></div>

<p>StateMachine states are defined by their <strong>name</strong>, a<strong> changed</strong> property, and <strong>transitions</strong>. Transitions define an <strong>action</strong> that triggers the move to a new state, and a <strong>target</strong> which defines the name of the state in which to move when the action notification is received by the StateMachine. The changed property of a state corresponds directly to the Command defined in the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/ShellFacade.as.html">ShellFacade</a>. When the StateMachine receives a notification to move to a new state, the Command defined in the changed property is executed.</p>
<p><img class="aligncenter size-full wp-image-182" title="pipingthemachinestatediagram" src="http://69.164.207.135/wp-content/uploads/2009/05/pipingthemachinestatediagram.png" alt="pipingthemachinestatediagram" width="491" height="131" /></p>
<p>We start off in the <em>Starting</em> state which simply mediates the shell application. From there we move to the <em>Plumbing</em> state which creates some of the initial Pipes, instantiates the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/logger/LoggerModule.as.html">LoggerModule</a> and connects it to the shell. From there we move to the <em>Assembling</em> state which requests a <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/logger/view/components/LoggerWindow.mxml.html">LoggerWindow</a> viewComponent to add to the stage. From here we move to the <em>Navigating</em> state which has no transitions associated with it. It is our final state and means that our application is configured and ready for the user to interact with. There is also a <em>Failing</em> state, which like the <em>Navigating</em> state has no transitions. If some portion of the configuration process were to fail, this state would be called to notify the user that something horrible has happened.</p>
<p>Communications between modules happens in a module's JunctionMediator. This mediator's viewComponent is a Junction. One issue to consider when utilizing dynamic modules is memory management. The connections made between modules with the Pipes utility need to be managed so that when they are disconnect there are no artifacts left to get in the way of Garbage Collection. This application utilizes an extended JunctionMediator defined by the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/common/view/ManagedJunctionMediator.as.html">ManagedJunctionMediator</a> class which defines a connection pool for the various pipes. When a module is instantiated, the connections are stored in a HashMap. Later, when we want to remove the module, the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/common/view/ManagedJunctionMediator.as.html">ManagedJunctionMediator</a> references its pool of connections and removes any connections related to that particular module. This is an area that needs more refinement, and while it works well for this demonstration, it could be further abstracted to make a more complete solution for this issue. The <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/view/ShellJunctionMediator.as.html">ShellJunctionMediator</a> is the only class extending <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/common/view/ManagedJunctionMediator.as.html">ManagedJunctionMediator</a> in this application.</p>
<p>It is important to note that a JunctionMediator's handleNotifications method needs to have the default in the switch set to super.handleNotification( note ). There are standard notifications that a JunctionMediator listens for that need to be handled. In addition, the listNotificationInterests method is handled a bit differently to accommodate this functionality.</p>
<h2>Adding a Doodad</h2>
<p>When you click on the Add Doodad button, the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/controller/AddNewDoodadCommand.as.html">AddNewDoodadCommand</a> is called. This command instantiates a new <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/doodad/DoodadModule.as.html">DoodadModule</a> and registers a <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/view/DoodadModuleMediator.as.html">DoodadModuleMediator</a> with the shell's core. The command then connects the module's pipes to the shell's STDIN and STDOUT pipes. After the module is wired to the shell for communication a notification is sent to get the UI associated with the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/doodad/DoodadModule.as.html">DoodadModule</a></p>
<p>The <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/doodad/DoodadModule.as.html">DoodadModule</a> is not a visual component. It extends <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/common/view/components/PipeAwareModule.as.html">PipeAwareModule</a>, which is itself an extension of ModuleBase. This is as opposed to Module, which is a visual class, but in this demonstration the visual components are created by the module and then sent to the shell for display. All of the visual components are mediated by their module, but control of their placement rests with the shell.</p>
<p>A <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/common/view/components/PipeAwareModule.as.html">PipeAwareModule</a> is instantiated with a unique identifier. This provides a way to differentiate it from other instances of the module easily. The <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/doodad/DoodadModule.as.html">DoodadModule</a> itself also creates a sequential integer identifier, but this is used here for the purposes of labeling and not marking the module for unique identification.</p>
<p>When the shell asks for a new Doodad, the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/common/model/message/UIQueryMessage.as.html">UIQueryMessage</a> of type GET is sent from the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/shell/view/ShellJunctionMediator.as.html">ShellJunctionMediator</a> and is received by the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/doodad/view/DoodadJunctionMediator.as.html">DoodadJunctionMediator</a>. The <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/doodad/DoodadModule.as.html">DoodadModule</a> then creates the visual component in the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/doodad/controller/CreateDoodadCommand.as.html">CreateDoodadCommand</a> and sends it back to the shell via a <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/common/model/message/UIQueryMessage.as.html">UIQueryMessage</a> of type SET. The shell then adds the component to the stage. When the Doodad's 'kill' button is pressed, the <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/modules/doodad/view/DoodadJunctionMediator.as.html">DoodadJunctionMediator</a> is ordered to send out another <a href="http://joelhooks.com/examples/pipemachine/srcview/source/com/joelhooks/pipingthemachine/common/model/message/UIQueryMessage.as.html">UIQueryMessage</a>, this time of type DESTROY which lets the shell know that it needs to unplug the module.</p>
<h2>Conclusion</h2>
<p>There is a lot going on here, and it is complex on many levels. There are huge advantages to engineering a complex application this way. It provides flexibility in terms of development allowing for growth and expansion of the system. This particular example is kept relatively simple, and in a real world application I would strive to make the modules more generic, abstracting out the Doodad-specific bits in the shell so that any module added would share common functionality in terms of memory management and basic mechanisms related to the visual components. Hopefully it provides a helpful overview for people looking to understand multicore applications with PureMVC and make use of some of the handy utilities the community has made available.</p>
<p>Let me know if you have any questions and I will do my best to answer them. If you have anything to add, or find any errors, please don't hesitate to let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://joelhooks.com/2009/05/18/piping-the-machine-puremvc-multicore-with-pipes-and-the-finite-state-machine-fsm/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Debugging your AIR/Flex application with Arthropod</title>
		<link>http://joelhooks.com/2009/02/05/debugging-your-airflex-application-with-arthropod/</link>
		<comments>http://joelhooks.com/2009/02/05/debugging-your-airflex-application-with-arthropod/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 22:42:56 +0000</pubDate>
		<dc:creator>Joel</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://joelhooks.com/?p=143</guid>
		<description><![CDATA[Arthropod is an external Debug trace window for Flash/Flex/AIR. Drop a simple class into your project and it will accept logging from the application/swf. I'm using it for debugging around the office with our internal project management AIR application with great success.]]></description>
			<content:encoded><![CDATA[<p><a href="http://arthropod.stopp.se/"><img src="http://69.164.207.135/wp-content/uploads/2009/02/header2.png" alt="" title="arthropod" width="500" height="108" class="aligncenter size-full wp-image-144" /></a></p>
<p>Arthropod is an external Debug trace window for Flash/Flex/AIR. Drop a simple class into your project and it will accept logging from the application/swf. I'm using it for debugging around the office with our internal project management AIR application with great success.</p>
]]></content:encoded>
			<wfw:commentRss>http://joelhooks.com/2009/02/05/debugging-your-airflex-application-with-arthropod/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Flex Date and Time (datetime) Picker Control</title>
		<link>http://joelhooks.com/2008/10/11/flex-date-and-time-datetime-picker-control/</link>
		<comments>http://joelhooks.com/2008/10/11/flex-date-and-time-datetime-picker-control/#comments</comments>
		<pubDate>Sun, 12 Oct 2008 02:10:14 +0000</pubDate>
		<dc:creator>Joel</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[components]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://joelhooks.com/?p=94</guid>
		<description><![CDATA[I saw one of these at some point, but couldn't find it when I needed it again. Pretty simple, the control has a property called selectedDate that returns a date object represented by the selected date and time. You can also feed it a Date and it will adjust to that. It is on a [...]]]></description>
			<content:encoded><![CDATA[<p>I saw one of these at some point, but couldn't find it when I needed it again. Pretty simple, the control has a property called selectedDate that returns a date object represented by the selected date and time. You can also feed it a Date and it will adjust to that. It is on a 12 hour clock. It dispatches a change event (Event.CHANGE) as a new date/time is selected.</p>
<p>There is an Inspectable property called minuteIncrement to adjust the increment on the minute stepper. I couldn't figure out how to have double digits on the 0-9 minutes. If anybody knows how I might achieve that, please let me know.</p>
<p><a href="/examples/datetime/srcview">Here's the Source</a></p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_TestDateTime_839284301"
			class="flashmovie"
			width="500"
			height="300">
	<param name="movie" value="/examples/datetime/TestDateTime.swf" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="/examples/datetime/TestDateTime.swf"
			name="fm_TestDateTime_839284301"
			width="500"
			height="300">
	<!--<![endif]-->
		
	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
]]></content:encoded>
			<wfw:commentRss>http://joelhooks.com/2008/10/11/flex-date-and-time-datetime-picker-control/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Django Authorization from Flex/AIR via PyAMF</title>
		<link>http://joelhooks.com/2008/09/21/django-authorization-from-flex-air-actionscript-via-pyamf/</link>
		<comments>http://joelhooks.com/2008/09/21/django-authorization-from-flex-air-actionscript-via-pyamf/#comments</comments>
		<pubDate>Mon, 22 Sep 2008 01:41:57 +0000</pubDate>
		<dc:creator>Joel</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[pyAMF]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://joelhooks.com/?p=88</guid>
		<description><![CDATA[Django views serve nicely as service end-points for Flex applications. Here are some notes on maintaining authenticated sessions between a Flex/Air/Flash application and your Django backend. gateway.py 1 2 3 4 5 6 7 8 from pyamf.remoting.gateway.django import DjangoGateway &#160; import myproject.myapp.views as views &#160; gw = DjangoGateway&#40;&#123; 'login' : views.login_user, 'logout' : views.logout_user, &#125;&#41; [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://69.164.207.135/wp-content/uploads/2008/09/pyamf-to-django.jpg" alt="" title="pyamf-to-django" width="500" height="121" class="aligncenter size-full wp-image-91" /></p>
<p>Django views serve nicely as service end-points for Flex applications. Here are some notes on maintaining authenticated sessions between a Flex/Air/Flash application and your Django backend.</p>
<p><strong>gateway.py</strong></p>

<div class="wp_codebox"><table><tr id="p886"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p88code6"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> pyamf.<span style="color: black;">remoting</span>.<span style="color: black;">gateway</span>.<span style="color: black;">django</span> <span style="color: #ff7700;font-weight:bold;">import</span> DjangoGateway
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> myproject.<span style="color: black;">myapp</span>.<span style="color: black;">views</span> <span style="color: #ff7700;font-weight:bold;">as</span> views
&nbsp;
gw = DjangoGateway<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'login'</span>                       : views.<span style="color: black;">login_user</span>,
    <span style="color: #483d8b;">'logout'</span>                     : views.<span style="color: black;">logout_user</span>,
<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><strong>views.py</strong></p>

<div class="wp_codebox"><table><tr id="p887"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code" id="p88code7"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> pyamf
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span> <span style="color: #ff7700;font-weight:bold;">import</span> auth
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">auth</span> <span style="color: #ff7700;font-weight:bold;">import</span> authenticate, login, logout
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">auth</span>.<span style="color: black;">decorators</span> <span style="color: #ff7700;font-weight:bold;">import</span> login_required
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">auth</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> User
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    pyamf.<span style="color: black;">register_class</span><span style="color: black;">&#40;</span> User,  <span style="color: #483d8b;">'django.contrib.auth.models.User'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ValueError</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Classes already registered&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> logout_user<span style="color: black;">&#40;</span>http_request<span style="color: black;">&#41;</span>:
    logout<span style="color: black;">&#40;</span>http_request<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> login_user<span style="color: black;">&#40;</span>http_request, username, password<span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">user</span> = authenticate<span style="color: black;">&#40;</span>username=username, password=password<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">user</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
        login<span style="color: black;">&#40;</span>http_request, <span style="color: #dc143c;">user</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">user</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
&nbsp;
@login_required
<span style="color: #ff7700;font-weight:bold;">def</span> registered_user_protected_function<span style="color: black;">&#40;</span>http_request<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;You are a registered user.&quot;</span>
&nbsp;
@login_required
<span style="color: #ff7700;font-weight:bold;">def</span> staff_protected_function<span style="color: black;">&#40;</span>http_request<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> http_request.<span style="color: #dc143c;">user</span>.<span style="color: black;">is_staff</span> <span style="color: #66cc66;">!</span>= <span style="color: #008000;">True</span>: <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;You are staff.&quot;</span></pre></td></tr></table></div>

<p><strong>from flex</strong></p>

<div class="wp_codebox"><table><tr id="p888"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p88code8"><pre class="actionscript" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">netConnection</span>:<span style="color: #0066CC;">NetConnection</span> = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">NetConnection</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0066CC;">netConnection</span>.<span style="color: #0066CC;">connect</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;http://mysite.com/gateway&quot;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">var</span> responder:Responder = <span style="color: #000000; font-weight: bold;">new</span> Responder<span style="color: #66cc66;">&#40;</span>loginResult, handleFault<span style="color: #66cc66;">&#41;</span>;
<span style="color: #0066CC;">netConnection</span>.<span style="color: #0066CC;">call</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;login&quot;</span>, responder, <span style="color: #ff0000;">&quot;username&quot;</span>, <span style="color: #ff0000;">&quot;password&quot;</span><span style="color: #66cc66;">&#41;</span></pre></td></tr></table></div>

<p>The http_request carries a reference to the currently authenticated user throughout the session. This works for web based Flex application as well as AIR applications on the desktop. Note that I am using a try/except on the pyamf class registration calls. Because this is session based, the classes only need to be registered once. Without the trap, it throws a TypeError letting you know the registration has already taken place.</p>
<p><a href="http://docs.djangoproject.com/en/dev/topics/auth/">Django User Authentication Documentation</a><br />
All of the various things you can do with authentication in Django. It is, of course, based mostly on the use of the very nice Django HTML template system. While those bits aren't handy to the likes of us, it is a good read either way.</p>
<p><a href="http://pyamf.org/wiki/ByteArrayExample">pyAMF ByteArray example</a><br />
This example shows the basic structure for setting up Django/Flex communication. It doesn't cover authentication, but covers a good bit of territory with examples in Flash and Flex.</p>
]]></content:encoded>
			<wfw:commentRss>http://joelhooks.com/2008/09/21/django-authorization-from-flex-air-actionscript-via-pyamf/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Integrating Adobe AIR, Cairngorm, PureMVC, LiveCycle Data Services (LCDS), MySQL and Hibernate</title>
		<link>http://joelhooks.com/2008/08/17/integrating-adobe-air-cairngormpuremvc-livecycle-data-services-lcds-mysql-and-hibernate/</link>
		<comments>http://joelhooks.com/2008/08/17/integrating-adobe-air-cairngormpuremvc-livecycle-data-services-lcds-mysql-and-hibernate/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 01:47:51 +0000</pubDate>
		<dc:creator>Joel</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[lcds]]></category>

		<guid isPermaLink="false">http://joelhooks.com/?p=68</guid>
		<description><![CDATA[This post is going to cover the use of Adobe AIR, PureMVC, cairngorm, MySQL, LiveCycle Data Services (LCDS), and Hibernate. It utilizes these tools to create a simple image management system. The focus is on the configuration of the server to integrate Hibernate with LCDS and access that configuration from an AIR client. The Tools:Flex [...]]]></description>
			<content:encoded><![CDATA[<p>This post is going to cover the use of Adobe AIR, PureMVC, cairngorm, MySQL, LiveCycle Data Services (LCDS), and Hibernate. It utilizes these tools to create a simple image management system. The focus is on the configuration of the server to integrate Hibernate with LCDS and access that configuration from an AIR client.<br id="h2h60" /></p>
<p><span id="more-68"></span></p>
<p><br id="w1qj" /><strong>The Tools:</strong><br id="tj9y" /><br id="tj9y0" /><a id="f60-" title="Flex Builder 3" href="http://www.adobe.com/products/flex/">Flex Builder 3</a> <br id="oqc1" /><br id="oqc10" />You can use any IDE that you prefer, but I will be using Flex Builder 3 (with Java Development Tools installed).<br id="w2fl0" /><br id="w2fl1" /><a id="ukgw" title="LiveCycle Data Services" href="http://www.adobe.com/products/livecycle/dataservices/">LiveCycle Data Services</a> [<a id="wmag" title="Download" href="http://www.adobe.com/go/trylivecycle_dataservices">Download</a>]<br id="w2fl2" /><br id="w2fl3" />For the purposes of demonstration, and many production needs that don't require the additional processing power, the free version of LCDS with the single CPU limitation is more than adequate. Why not use BlazeDS? Well, BlazeDS doesn't have the RTMP support or the Hibernate adapters that are included with its big brother LCDS. My primary goal is to get Hibernate functioning with Flex/AIR, and LCDS is the shortest (easiest?) route that I am currently aware of. There are several ongoing projects to bring a hibernate adapter to BlazeDS, and it will be interesting to follow what comes about from those efforts.<br id="h2h61" /><br id="w1qj4" /><a id="luj." title="Cairngorm Enterprise 2.2.1" href="http://opensource.adobe.com/wiki/display/cairngorm/Cairngorm">Cairngorm Enterprise 2.2.1</a> <br id="h2h62" /><br id="h2h63" />Cairngorm is a versatile, lightweight MVC framework updated and maintained by Adobe. It is an open-source project, and extremely useful in a wide variety of use cases. That said, it doesn't provide me with the full feature set I desire in my MVC solution. It does, however, provide a most excellent service locator pattern that works extremely well with LCDS. The service locator is the only aspect of Cairngorm I am going to use in this exercise.<br id="zm1q" /><br id="zm1q0" /><a id="sdvb" title="PureMVC 2.0.1" href="http://www.puremvc.org/">PureMVC Multicore 1.0.5</a> <br id="daf70" /><br id="daf71" />PureMVC is a robust open source MVC solution. It is a weightier than cairngorm in its approach, but that extra weight provides useful patterns for approaching view-centric RIA development. Simply put, I can't live without the Mediator's control over my view components. The Proxy pattern provides a highly controlled method for accessing, sorting, and maintaining my data. The Command is essentially the same as the system found in Cairngorm, but for the purposes of this project I will be using mostly PureMVC with cairngorm's EnterpriseServiceLocator providing the connectivity with LCDS on the backend.<br id="x0.w2" /><br id="eue0" /><a id="al-2" title="Hibernate" href="http://www.hibernate.org/344.html">Hibernate</a><br id="eue01" /> <br id="xuri0" />Hibernate is an Object/Relational Management framework for Java. It provides seemingly magical functionality in this capacity. It isn't really magic, as digging through its open source will demonstrate, but it is highly configurable and generally easy to use. It abstract painful CRUD operations and solves the majority of the problems you encounter when combining relational databases with object oriented software systems.<br id="y9xq" /><br id="y9xq0" /><a id="zdkq" title="Hibernate Tools" href="http://www.hibernate.org/255.html">Hibernate Tools</a> <br id="y9xq1" /><br id="y9xq2" />Hibernate tools is an Eclipse (Flex Builder) plugin that will reverse engineer Java objects and Hibernate config files from your database.<br id="ofra0" /><br id="ofra1" /><a id="o8m9" title="MySQL" href="http://dev.mysql.com/">MySQL</a> <br id="ofra2" /><br id="ofra3" />MySQL is the relational database of choice for this series. It should be relatively painless to utilize your preferred relational database, but for the sake of simplicity, and my lack of experience with other systems, that is what I will be utilizing here.<br id="vl2q" /><br id="vl2q0" />This is a lot of ground to cover. It is a daunting task, but the results are worth the effort. Once you have a level of comfort with the tools, the resulting systems provide a maintainable structure that provides your users with a rich visual experience. Data is maintained and updated across all clients accessing the system. LCDS allows for users to interact with one another, provides offline synchronization capabilities, as well as a robust persistence framework via the LCDS Hibernate adapter. Flex provides a consistent cross-platform user experience and applications are easily brought to the desktop with the AIR runtime.<br id="w1qj6" /><br id="r8.s" /><strong>The Project:</strong><br id="r8.s6" /><br id="r8.s7" />This project is a simple image gallery that stores images in albums.<br id="m7dp" /><br id="m7dp0" /><strong>The Setup:</strong><br id="m7dp7" /><br id="m7dp8" />It is assumed that you can download and install all of the above tools, so I am not going to detail that process. There are some details in the process that I will cover here. These are annomolies, or frustrating problems that took some measure of significant time searching down solutions for.<br id="e2q1" /><br id="e2q10" /><strong>MySQL</strong><br id="qhxk0" /></p>
<div id="p92h" style="margin-left: 40px;">DROP TABLE IF EXISTS `album`;<br id="qhxk1" style="color: #073763;" />CREATE TABLE `album` (<br id="qhxk2" style="color: #073763;" /> `id` int(11) NOT NULL auto_increment,<br id="qhxk3" style="color: #073763;" /> `name` varchar(256) default NULL,<br id="qhxk4" style="color: #073763;" /> `description` varchar(1024) default NULL,<br id="qhxk5" style="color: #073763;" /> `is_active` tinyint(1) default NULL,<br id="qhxk6" style="color: #073763;" /> `display_order` int(11) NOT NULL default '0',<br id="qhxk7" style="color: #073763;" /> `updated_on` datetime default NULL,<br id="qhxk8" style="color: #073763;" /> `created_on` datetime default NULL,<br id="qhxk10" style="color: #073763;" /> `mp3_url` varchar(256) default NULL,<br id="qhxk11" style="color: #073763;" /> PRIMARY KEY  (`id`)<br id="qhxk14" style="color: #073763;" />) ENGINE=InnoDB DEFAULT CHARSET=utf8;<br id="qhxk15" style="color: #073763;" /><br id="qhxk16" style="color: #073763;" />--<br id="qhxk17" style="color: #073763;" />-- Table structure for table `image`<br id="qhxk18" style="color: #073763;" />--<br id="qhxk19" style="color: #073763;" /><br id="qhxk20" style="color: #073763;" />DROP TABLE IF EXISTS `image`;<br id="qhxk21" style="color: #073763;" />CREATE TABLE `image` (<br id="qhxk22" style="color: #073763;" /> `id` int(11) NOT NULL auto_increment,<br id="qhxk23" style="color: #073763;" /> `image` longblob NOT NULL,<br id="qhxk24" style="color: #073763;" /> `album_id` int(11) NOT NULL,<br id="qhxk25" style="color: #073763;" /> `sequence` int(11) NOT NULL,<br id="qhxk26" style="color: #073763;" /> PRIMARY KEY  (`id`),<br id="qhxk27" style="color: #073763;" /> KEY `album_id` (`album_id`),<br id="qhxk28" style="color: #073763;" /> CONSTRAINT `image_ibfk_1` FOREIGN KEY (`album_id`) REFERENCES `album` (`id`)<br id="qhxk29" style="color: #073763;" />) ENGINE=InnoDB DEFAULT CHARSET=utf8;</div>
<p>This is the database schema that will be used in the project. It is a simple two table structure. Note that we are using the <a id="gf29" title="INNOdb" href="http://en.wikipedia.org/wiki/InnoDB">INNOdb</a> engine for the tables. I use <a id="rksr" title="XAMPP" href="http://www.apachefriends.org/en/xampp.html">XAMPP</a> for my localhost configuration, and INNOdb is actually disabled by default. It is important to use INNOdb, as it supports foreign key constraints. These constraints will be used by the Hibernate Tools reverse engineering scripts to determine relationships across our object classes. While it isn't strictly necessary to use these tools, it saves a lot of initial typing.<br id="p58p" /><br id="p58p0" />This database structure is simple on purpose. You could add many other tables/fields to make this a more robust system. For the purposes of demonstration we will be applying KISS principles. Some ideas for expantion would be user accounts, thumbnails, slideshows, tagging, rating, or any other features that you might find in a photo album.<br id="lovt" /><br id="lovt0" />Create a database called 'slideshow' and apply the above SQL to create the two tables we will use for this demonstration.<br id="isk9" /><br id="isk90" /><strong>LCDS</strong><br id="isk91" /><br id="isk92" />The default installation of LCDS contains some sample projects as well as a template project called LCDS. Because of limitations with the free single-cpu license, you are not able to run multiple applications. I move the default samples project out and rename the lcds project to slideshow (or better yet, move the lcds folder out and place a renamed copy of it back in the webapps folder.) You will also need to rename the context file that initializes the transaction manager utilized by Hibernate located in the {lcds-root}/tomcat/conf/Catalina/localhost folder. I removed the lcds-samples.xml, as well as the lcds.xml files after first making a copy of lcds.xml and renaming it slideshow.xml to match our application.<br id="x8au" /><br id="e7ev" />NOTE: If you are using Flex Builder, you will need to install the Java Development Tools. If you are using Eclipse, you will need to install the Flex Builder plugin. In this demonstration, I am using Flex Builder 3 with the Java Development Tools added on.<br id="e7ev0" /><br id="x8au0" />In Flex Builder create a new Java Project named Slideshow. Select the Create project from existing source option and navigate to {lcds-root}/tomcat/webapps/slideshow/WEB-INF. Choose next, and ensure that the Default output path is set to Slideshow/classes. By default, this might be set to bin-debug, and this is not appropriate for an LCDS application. The server will not know where to look for the compiled classes! Click Finish.<br id="mi9i" /><br id="mi9i0" /></p>
<div id="bgp7" style="padding: 1em 0pt; text-align: center;"><img id="pu8x" style="width: 443px; height: 365px;" src="http://docs.google.com/File?id=dfnsxvcr_4c2dhthpz_b" alt="" /><br id="pu8x0" />Initial Slideshow project structure<br id="et6l0" /><br id="et6l1" /></div>
<div id="d8nz" style="padding: 1em 0pt; text-align: center;">
<div id="et6l2" style="text-align: left;">Open the Hibernate perspective in Flex Builder. In the Hibernate Configurations tab, right-click and select Add Configuration... to open the configuration dialog. Name the configuration slideshow-hibernate, select your project, hit Setup... for your property file and select Create new... and place it in the root of your project. Click Setup... for your configuration file and select Create new... to create an initial hibernate.cfg.xml that we will use to connect to our database for reverse engineering of the tables into Java POJOs and Hibernate mapping files. Select MySQL 5(InnoDB) as the database dialect, org.gjt.mm.mysql.Driver as the Driver class, jdbc:mysql://localhost/slideshow as your connection URL, and enter your database username/password before clicking finish. The configuration should now be available in the Hibernate Configurations tab. Open the Database, and you should see your database and the tables contained within:<br id="hx87" /><br id="hx870" /></p>
<div id="r_op" style="padding: 1em 0pt; text-align: center;"><img id="lxk8" style="width: 350px; height: 417px;" src="http://docs.google.com/File?id=dfnsxvcr_5dptm6dcp_b" alt="" /><br id="lxk80" />Hibernate Configuration Wizard results<br id="lxk82" /><br id="lxk83" /></p>
<div id="lxk84" style="text-align: left;"><br id="lxk85" /></div>
</div>
<div id="zdfg" style="margin-left: 40px;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br id="zdfg1" style="color: #0b5394;" />&lt;!DOCTYPE hibernate-configuration PUBLIC<br id="zdfg3" style="color: #0b5394;" /> "-//Hibernate/Hibernate Configuration DTD 3.0//EN"<br id="zdfg5" style="color: #0b5394;" /> "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&gt;<br id="zdfg7" style="color: #0b5394;" />&lt;hibernate-configuration&gt;<br id="zdfg9" style="color: #0b5394;" /> &lt;session-factory&gt;<br id="zdfg11" style="color: #0b5394;" /> &lt;property name="hibernate.connection.driver_class"&gt;org.gjt.mm.mysql.Driver&lt;/property&gt;<br id="zdfg13" style="color: #0b5394;" /> &lt;property name="hibernate.connection.password"&gt;mypassword&lt;/property&gt;<br id="zdfg15" style="color: #0b5394;" /> &lt;property name="hibernate.connection.url"&gt;jdbc:mysql://localhost/slideshow&lt;/property&gt;<br id="zdfg17" style="color: #0b5394;" /> &lt;property name="hibernate.connection.username"&gt;root&lt;/property&gt;<br id="zdfg19" style="color: #0b5394;" /> &lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.MySQL5InnoDBDialect&lt;/property&gt;<br id="zdfg21" style="color: #0b5394;" /> &lt;/session-factory&gt;<br id="zdfg23" style="color: #0b5394;" />&lt;/hibernate-configuration&gt;<br id="zdfg25" /><br id="zdfg26" /></div>
<p>The resulting hibernate.cfg.xml should look like the above.<br id="yb70" /><br id="yb700" />From the Run menu, select Hibernate Code Generation, and select Open Hibernate Code Generation Dialog... to create a reverse engineering configuration to generate our POJOs and Hibernate mapping files. Click the "New launch configuration" icon and rename the configuration "slideshow-configuration". In the Console configuration dialog select our slidwshow-hibernate configuration that we created in the previous step. Brows to the src directory of our project in the Output directory selection. Click the "Reverse engineer from JDBC Connection" checkbox. Enter "slideshow.data" in the package text input area. Click the setup button for reveng.xml and choose "Create new..." and place the file in the root of our project. Move to the "Exporters Tab" and choose Domain code (.java), Hibernate XML Mappings (.hbm.xml), and Hibernate XML Configuration (.cfg.xml). Didn't we already create a hibernate.cfg.xml? Yes, but this generated version will be placed in the src directory, and will contain the appropriate references to our mapping files. The first configuration is simply to tell the generator where to connect to our database. Switch to the Refresh tab and select "Refresh resources upon completion." so that our project structure will be refreshed after we click Run. Click Run.<br id="mu7g" /><br id="mu7g0" />From the Package Explorer tab, you will see that our .java classes have been generated, as well as their appropriate sidecar .hbm.xml files. The album class containes a Set called images, and the Image class contains an Album property. Take a look at the .hbm.xml files and take note of the defined relationships. The Hibernate reverse engineering has successfully traversed our database structure and created the appropriate relationsips!<br id="g8l4" /><br id="g8l40" />It is worth noting that the Hibernate reverse engineering tools could concievably take care of the following steps. This is on my list of things to explore, but for now we will define our LCDS destinations and Actionscript value objects the old fashioned way. By hand. Yick.<br id="pyn6" /><br id="pyn60" />As a final step we will add cascading and a retrieve all query to our album.hbm.xml like this:<br id="d8nz0" /><br id="d8nz1" /></p>
<div id="d8nz2" style="margin-left: 40px; color: #0b5394;">&lt;?xml version="1.0"?&gt;<br id="d8nz3" />&lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br id="d8nz4" />"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;<br id="d8nz5" />&lt;!-- Generated Aug 17, 2008 1:02:52 PM by Hibernate Tools 3.2.2.GA --&gt;<br id="d8nz6" />&lt;hibernate-mapping&gt;<br id="d8nz7" /> &lt;class name="slideshow.data.Album" table="album" catalog="slideshow"&gt;<br id="d8nz8" /> &lt;id name="id" type="java.lang.Integer"&gt;<br id="d8nz9" /> &lt;column name="id" /&gt;<br id="d8nz10" /> &lt;generator class="identity" /&gt;<br id="d8nz11" /> &lt;/id&gt;<br id="d8nz12" /> &lt;property name="name" type="string"&gt;<br id="d8nz13" /> &lt;column name="name" length="256" /&gt;<br id="d8nz14" /> &lt;/property&gt;<br id="d8nz15" /> &lt;property name="description" type="string"&gt;<br id="d8nz16" /> &lt;column name="description" length="1024" /&gt;<br id="d8nz17" /> &lt;/property&gt;<br id="d8nz18" /> &lt;property name="isActive" type="java.lang.Boolean"&gt;<br id="d8nz19" /> &lt;column name="is_active" /&gt;<br id="d8nz20" /> &lt;/property&gt;<br id="d8nz21" /> &lt;property name="displayOrder" type="int"&gt;<br id="d8nz22" /> &lt;column name="display_order" not-null="true" /&gt;<br id="d8nz23" /> &lt;/property&gt;<br id="d8nz24" /> &lt;property name="updatedOn" type="timestamp"&gt;<br id="d8nz25" /> &lt;column name="updated_on" length="19" /&gt;<br id="d8nz26" /> &lt;/property&gt;<br id="d8nz27" /> &lt;property name="createdOn" type="timestamp"&gt;<br id="d8nz28" /> &lt;column name="created_on" length="19" /&gt;<br id="d8nz29" /> &lt;/property&gt;<br id="d8nz30" /> &lt;property name="mp3Url" type="string"&gt;<br id="d8nz31" /> &lt;column name="mp3_url" length="256" /&gt;<br id="d8nz32" /> &lt;/property&gt;<br id="d8nz33" /> &lt;set name="images" inverse="true" cascade="all"&gt;<br id="d8nz34" /> &lt;key&gt;<br id="d8nz35" /> &lt;column name="album_id" not-null="true" /&gt;<br id="d8nz36" /> &lt;/key&gt;<br id="d8nz37" /> &lt;one-to-many class="slideshow.data.Image" /&gt;<br id="d8nz38" /> &lt;/set&gt;<br id="d8nz39" /> &lt;/class&gt;<br id="d8nz40" /> &lt;query name="all.albums"&gt;from Album&lt;/query&gt;<br id="d8nz41" />&lt;/hibernate-mapping&gt;</div>
<p><br id="vkzx1" />These two changes are the only changes neccessary. The generator has taken care of everything else.<br id="vkzx2" /><br id="s08i0" /><strong>Defining the LCDS Destinations</strong><br id="s08i2" /><br id="s08i3" />Now that we have set up the server side Java application, it is neccessary to create destinations for our client to communicate with. In the flex directory of our project, there are a number of xml configuration files. The default configuration will be sufficient in all cases except for the data-management-config.xml. This is the file that will contain our destinations.<br id="dp:8" /><br id="dp:80" />This is the basic configuration for our destinations defining the relationships between our objects:<br id="et6l3" /></div>
</div>
<div id="dp:81" style="margin-left: 40px;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br id="dp:83" style="color: #3d85c6;" />&lt;service id="data-service" <br id="dp:85" style="color: #3d85c6;" /> class="flex.data.DataService"&gt;<br id="dp:87" style="color: #3d85c6;" /><br id="dp:88" style="color: #3d85c6;" /> &lt;adapters&gt;<br id="dp:810" style="color: #3d85c6;" /> &lt;adapter-definition id="actionscript" class="flex.data.adapters.ASObjectAdapter" default="true"/&gt;<br id="dp:812" style="color: #3d85c6;" /> &lt;adapter-definition id="java-dao" class="flex.data.adapters.JavaAdapter"/&gt;<br id="dp:814" style="color: #3d85c6;" /> &lt;/adapters&gt;<br id="dp:816" style="color: #3d85c6;" /><br id="dp:817" style="color: #3d85c6;" /> &lt;default-channels&gt;<br id="dp:819" style="color: #3d85c6;" /> &lt;channel ref="my-rtmp"/&gt;<br id="dp:821" style="color: #3d85c6;" /> &lt;/default-channels&gt;<br id="dp:823" style="color: #3d85c6;" /> <br id="dp:825" style="color: #3d85c6;" /> &lt;destination id="AlbumHibernate"&gt;<br id="dp:827" style="color: #3d85c6;" /> &lt;adapter ref="java-dao" /&gt;<br id="dp:829" style="color: #3d85c6;" /> &lt;properties&gt;<br id="dp:831" style="color: #3d85c6;" /> &lt;use-transactions&gt;true&lt;/use-transactions&gt;<br id="dp:833" style="color: #3d85c6;" /> &lt;source&gt;flex.data.assemblers.HibernateAssembler&lt;/source&gt;<br id="dp:835" style="color: #3d85c6;" /> &lt;scope&gt;application&lt;/scope&gt;<br id="dp:837" style="color: #3d85c6;" /> &lt;metadata&gt;<br id="dp:839" style="color: #3d85c6;" /> &lt;!--This is the unique identifier from the hibernate-entity bean --&gt;<br id="dp:841" style="color: #3d85c6;" /> &lt;identity property="id"/&gt;<br id="dp:843" style="color: #3d85c6;" /> &lt;one-to-many property="images" destination="ImageHibernate" lazy="true" /&gt;    <br id="dp:845" style="color: #3d85c6;" /> &lt;/metadata&gt;<br id="dp:847" style="color: #3d85c6;" /> &lt;network&gt;<br id="dp:849" style="color: #3d85c6;" /> &lt;session-timeout&gt;0&lt;/session-timeout&gt;<br id="dp:851" style="color: #3d85c6;" /> &lt;/network&gt;<br id="dp:853" style="color: #3d85c6;" /> &lt;server&gt;<br id="dp:855" style="color: #3d85c6;" /> &lt;hibernate-entity&gt;slideshow.data.Album&lt;/hibernate-entity&gt;<br id="dp:857" style="color: #3d85c6;" /> &lt;fill-method&gt;<br id="dp:859" style="color: #3d85c6;" /> &lt;name&gt;fill&lt;/name&gt;<br id="dp:861" style="color: #3d85c6;" /> &lt;params&gt;java.util.List&lt;/params&gt;<br id="dp:863" style="color: #3d85c6;" /> &lt;/fill-method&gt;<br id="dp:865" style="color: #3d85c6;" /> &lt;fill-configuration&gt;<br id="dp:867" style="color: #3d85c6;" /> &lt;use-query-cache&gt;false&lt;/use-query-cache&gt;<br id="dp:869" style="color: #3d85c6;" /> &lt;allow-hql-queries&gt;true&lt;/allow-hql-queries&gt;<br id="dp:871" style="color: #3d85c6;" /> &lt;/fill-configuration&gt;<br id="dp:873" style="color: #3d85c6;" /> &lt;/server&gt;<br id="dp:875" style="color: #3d85c6;" /> &lt;/properties&gt;<br id="dp:877" style="color: #3d85c6;" /> &lt;/destination&gt;  <br id="dp:879" style="color: #3d85c6;" /><br id="dp:880" style="color: #3d85c6;" /> &lt;destination id="ImageHibernate"&gt;<br id="dp:882" style="color: #3d85c6;" /> &lt;adapter ref="java-dao" /&gt;<br id="dp:884" style="color: #3d85c6;" /> &lt;properties&gt;<br id="dp:886" style="color: #3d85c6;" /> &lt;use-transactions&gt;true&lt;/use-transactions&gt;<br id="dp:888" style="color: #3d85c6;" /> &lt;source&gt;flex.data.assemblers.HibernateAssembler&lt;/source&gt;<br id="dp:890" style="color: #3d85c6;" /> &lt;scope&gt;application&lt;/scope&gt;<br id="dp:892" style="color: #3d85c6;" /> &lt;metadata&gt;<br id="dp:894" style="color: #3d85c6;" /> &lt;!--This is the unique identifier from the hibernate-entity bean --&gt;<br id="dp:896" style="color: #3d85c6;" /> &lt;identity property="id"/&gt;<br id="dp:898" style="color: #3d85c6;" /> &lt;many-to-one property="album"  destination="AlbumHibernate" lazy="true" /&gt;<br id="dp:8100" style="color: #3d85c6;" /> &lt;/metadata&gt;<br id="dp:8102" style="color: #3d85c6;" /> &lt;network&gt;<br id="dp:8104" style="color: #3d85c6;" /> &lt;session-timeout&gt;0&lt;/session-timeout&gt;<br id="dp:8106" style="color: #3d85c6;" /> &lt;/network&gt;<br id="dp:8108" style="color: #3d85c6;" /> &lt;server&gt;<br id="dp:8110" style="color: #3d85c6;" /> &lt;hibernate-entity&gt;slideshow.data.Image&lt;/hibernate-entity&gt;<br id="dp:8112" style="color: #3d85c6;" /> &lt;fill-method&gt;<br id="dp:8114" style="color: #3d85c6;" /> &lt;name&gt;fill&lt;/name&gt;<br id="dp:8116" style="color: #3d85c6;" /> &lt;params&gt;java.util.List&lt;/params&gt;<br id="dp:8118" style="color: #3d85c6;" /> &lt;/fill-method&gt;<br id="dp:8120" style="color: #3d85c6;" /> &lt;fill-configuration&gt;<br id="dp:8122" style="color: #3d85c6;" /> &lt;use-query-cache&gt;false&lt;/use-query-cache&gt;<br id="dp:8124" style="color: #3d85c6;" /> &lt;allow-hql-queries&gt;true&lt;/allow-hql-queries&gt;<br id="dp:8126" style="color: #3d85c6;" /> &lt;/fill-configuration&gt;<br id="dp:8128" style="color: #3d85c6;" /> &lt;/server&gt;<br id="dp:8130" style="color: #3d85c6;" /> &lt;/properties&gt;<br id="dp:8132" style="color: #3d85c6;" /> &lt;/destination&gt;              <br id="dp:8134" style="color: #3d85c6;" />&lt;/service&gt;<br id="orhv" /></div>
<div id="orhv0"><br id="fegk0" /><br id="fegk1" /><br id="orhv1" /><strong>The Client</strong><br id="orhv3" /><br id="orhv4" />The client will be an Adobe AIR client. Why AIR? Well, for this particular demonstration, an image gallery, it is neccesary to pull images from the users harddrive and upload them as bytearrays to the server for storage in the database. With the current Flash Player Runtime (9 at the time of this writing) you cannot do this due to security sandbox restrictions. The good news is that this particular restriction is being relaxed in Flash Player 10, but for now it is not possible outside of AIR, or with roundtrip trickery via a web service.<br id="vp3g" /><br id="vp3g0" />"But wait, I thought we were applying KISS principles? Cairngorm AND PureMVC? What's up with that?"<br id="fdxw" /><br id="fdxw0" />Cairngorm is a nice framework, but PureMVC provides robust control over your view layer that Cairngorm lacks. Cairngorm's ServiceLocator (or EnterpriseServiceLocator in this case) is extremely convenient and provides easy access to our data services. In the context of this application, the ServiceLocator is the only piece of Cairngorm we are going to use. When I originally built this application, it was actually as a means to learn about the Cairngorm framework, but I found myself missing PureMVC the entire time I was working with it. So I am taking this opportunity to demonstrate the combination of these two frameworks as a means to create a robust MVC driven LCDS connected application.<br id="x.28" /><br id="x.280" /></p>
<div id="oid5" style="padding: 1em 0pt; text-align: center;">
<div id="io4z" style="padding: 1em 0pt; text-align: center;"><img id="ct.:" style="width: 339px; height: 761px;" src="http://docs.google.com/File?id=dfnsxvcr_7gvk8m2gs_b" alt="" /><br id="ct.:0" /> Flex Project Structure<br id="g2eb2" /></div>
</div>
<p>The project structure is typical PureMVC, with model, view and controller folders added under the slideshow package. The focus of this tutorial is the server side configuration. I'm not going to go into detail about constructing the client application, but I am going to summarize what the classes do:<br id="h.dv" /> <br id="h.dv0" /> <strong>Slideshow.mxml</strong><br id="h.dv2" /> This is our main application window. It calls a reference to the SlideshowServiceLocator component to initialize the EnterpriseServiceLocator singleton class. It also contains references to our two Value Object classes. This is neccesary to send typed objects back and forth over the wire. Until the VOs are called, they will be transfered as generic objects. Slideshow.mxml also initializes the PureMVC ApplicationFacade. <br id="i:s60" /> <br id="i:s61" /> <strong>SlideshowServiceLocator.mxml</strong><br id="i:s62" /> This component is an extension of the Cairngorm Enterpriese EnterpriseServiceLocator class. This is the place where you define your channels and services to facilitate communication with the LCDS rtmp end-point. If you want to change the end-point from localhost to reflect your personal configuration or a remote server, this is the place to do it.<br id="n63n0" /> <br id="n63n1" /> <strong>*Command.as</strong><br id="n63n3" /> These classes initialize the PureMVC proxy and view components.<br id="djdo" /> <br id="djdo0" /> <strong>*Events.as</strong><br id="djdo2" /> These are custom events. They are very simple extensions of the Event class, but they carry references to value objects to make life easier.<br id="er.p" /> <br id="er.p0" /> <strong>*VO.as</strong><br id="er.p2" /> The value objects mirror the POJO objects on our server side. They are [Managed], meaning they are monitored for changes by LCDS. Managed classes are [Bindable] by default. There is also additional metadata referencing the remote class so that our objects will be stongly typed over the wire.<br id="g-g5" /> <br id="kt.2" /> <strong>ApplicationMediator.as</strong><br id="kt.20" /> This is the mediator for the main application window. It registers the mediators that monitor and control the sub-components of the application.<br id="kt.21" /> <br id="gt_i" /> <strong>*Mediator.as</strong><br id="gt_i0" /> The mediators monitor for changes in our view components and respond to notifications from commands, proxies, and other mediators. In this application, there are not many notifications being sent around, but I left the methods in place for future expansion.<br id="gt_i1" /> <strong><br id="g-g50" /> AlbumListProxy.as</strong><br id="g-g51" /> This proxy is where we grab the list of albums from the server. This proxy grabs an instance of the EnterpriseServiceLocator and calls the "albums.all" query to fill the data property of the proxy. When the list of albums is retrieved, we assign each album an individual proxy to lord over it.<br id="g-g52" /> <br id="g-g53" /> <strong>AlbumProxy.as</strong><br id="g-g54" /> AlbumProxy contains methods to manipulate albums. Add images, delete images, delete the album, etc. While it is wholly possible to place these methods inside the actual view components (ServiceLocator makes it very easy), it is better form to seperate the manipulation of our data model from our view layer. View components should be stupid, ignorant of anything outside of displaying the data passed to them. With this application, I actually did data manipulation in the view components, but then refactored to follow the proxied data methodology. This is how I approach these things a lot of the times. Create a monolithic view component, break it into smaller components, mediate those deserving of such treatment, and finally proxy the data manipulation methods contained in the objects. I've found that as I gain experience, I am able to plan the broader structure without having to use this approach, but "make it work, then make it work better" is still a valid approach.</div>
<div id="x4ef2" class="Section1" style="font-family: Verdana;">
<p id="x4ef131" class="MsoNormal"><strong>In Conclusion:</strong></p>
<p id="cyxy" class="MsoNormal">This application is possibly too simple for this elaborate setup. I chose this particular project because it is actually a piece of a larger image management system that I have planned. You might also notice, that while I call it 'Slideshow", we never actually run a slideshow! It could, with some simple additions, and lists of images are only interesting when they move and have music thumping behind them. This technology stack is very exciting, and presents many possibilities for a wide variety of application development. For small scale development, the single cpu LCDS license is probably sufficient. One thing I have not done is stress test LCDS to see exactly what it can handle on a single CPU.<br id="cyxy1" /></p>
<p id="j:qy" class="MsoNormal">Below is the exported web application archive. It can be extraced to your {lcds-root}/tomcat/webapps/ folder and contains all of the Java libraries, as well as the SWCs that I used on the Flex side. The Flex project, AIR rather, is contained in the flex-src folder of the java project. To get these projects into Flex Builder, follow these steps:<br id="j:qy0" /></p>
<p id="f0wt0" class="MsoNormal">In the Flex Development perspective choose Import&gt;Flex Project and select Project folder. Navigate to the {lcds-root}/tomcat/webapps/slideshow/WEB-INF/flex-src/slideshow-tutorial folder, select it, and then hit finish.<br id="f0wt1" /></p>
<p id="u:hz" class="MsoNormal">In the Java perspective, choose file&gt;new&gt;Java Project and choose "Create project from existing source." Navigate to {lcds-root}/tomcat/webapps/slideshow/WEB-INF and select this folder.<br id="u:hz0" /></p>
<p id="u:hz2" class="MsoNormal">Both the Flex and Java projects should now be properly imported.<br id="u:hz3" /></p>
<p>If you find glaring errors, omissions, or any other problems with this project, please let me know so that I can improve upon it for others.</p>
<p><a href="http://joelhooks.com/slideshow.zip">slideshow.zip (22.7mb)</a></p>
<p>[The zip is large. This is because of the JAR libs in the java project. Specifically those related to Acrobat. <a href="http://joelhooks.com/slideshow_small.zip">Here (1.7mb)</a> is a version with no JARs.]</div>
]]></content:encoded>
			<wfw:commentRss>http://joelhooks.com/2008/08/17/integrating-adobe-air-cairngormpuremvc-livecycle-data-services-lcds-mysql-and-hibernate/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Christian Cantrell&#039;s ever-growing selection of useful Actionscript 3/AIR libraries.</title>
		<link>http://joelhooks.com/2008/03/23/christian-cantrells-ever-growing-selection-of-useful-actionscript-3air-libraries/</link>
		<comments>http://joelhooks.com/2008/03/23/christian-cantrells-ever-growing-selection-of-useful-actionscript-3air-libraries/#comments</comments>
		<pubDate>Mon, 24 Mar 2008 04:05:13 +0000</pubDate>
		<dc:creator>Joel</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[libraries]]></category>

		<guid isPermaLink="false">http://joelhooks.com/2008/03/23/christian-cantrells-ever-growing-selection-of-useful-actionscript-3air-libraries/</guid>
		<description><![CDATA[Here's the full list of what he has on Google Code. The CoreLib is essential, but he's been busy writing useful libraries for AIR. I've used the notification library, which has some great features and makes notifications on the desktop sensible. The exchange library is interesting, for sure. They are all worth checking out. There [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/u/christian.cantrell/">Here's the full list of what he has on Google Code</a>.</p>
<p>The CoreLib is essential, but he's been busy writing useful libraries for AIR. I've used the notification library, which has some great features and makes notifications on the desktop sensible. The exchange library is interesting, for sure. They are all worth checking out.</p>
<p>There are also a number of interesting example applications using AIR, including a <a href="http://code.google.com/p/snakeeye/">motion detection application</a>, an <a href="http://code.google.com/p/s3e/">Amazon S3 interface</a>, a <a href="http://code.google.com/p/screenprotectionfactor/">screen saver</a>, and an <a href="http://code.google.com/p/lineup/">MS Exchange calendar</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://joelhooks.com/2008/03/23/christian-cantrells-ever-growing-selection-of-useful-actionscript-3air-libraries/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Complex DataGrid filterFunction in Flex/Air</title>
		<link>http://joelhooks.com/2008/03/14/complex-datagrid-filterfunction-in-flexair/</link>
		<comments>http://joelhooks.com/2008/03/14/complex-datagrid-filterfunction-in-flexair/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 04:52:02 +0000</pubDate>
		<dc:creator>Joel</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[OCD]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://joelhooks.com/2008/03/14/complex-datagrid-filterfunction-in-flexair/</guid>
		<description><![CDATA[So I need to add robust user controlled filtering options in the application I am working on. This problem has dogged me for a month or two, with my co-workers politely insisting on more and better ways to filter their data. This is completely understandable. When you are staring down a datagrid that is virtually [...]]]></description>
			<content:encoded><![CDATA[<p>So I need to add robust user controlled filtering options in the application I am working on. This problem has dogged me for a month or two, with my co-workers politely insisting on more and better ways to filter their data. This is completely understandable. When you are staring down a datagrid that is virtually 12 feet long, getting to what you actually want to see is important.</p>
<p>This <a href="http://www.brucephillips.name/blog/index.cfm/2006/11/23/Sort-An-ArrayCollection-By-Multiple-Fields-and-Filter-An-ArrayCollection-By-Multiple-Fields-In-Flex">2006 article from Bruce Phillips</a> was a big help in the basic concept of multiple input filtering. As is his normal style, it is littered with good references to the source material from his research. This is only considering two filter parameters, however, and I need to consider n parameters, that will probably shift as the needs of the end user grow.</p>
<p>The problem is that each new filtering parameter exponentially increases the complexity of the filterFunction. I can see the pattern, but I haven't quite reached the epiphany that I need to break it down into one of those tight little functions I see real programmers creating (unfortunately, I haven't seen any that address my specific problem).</p>
<p>I thought I'd share my naive, and perhaps confusing filterFunction. It would be great to hear how others approach this problem, and come up with a concise solution.</p>
<p>This function utilizes a TextInput to get text search input from the user. It uses<br />
a series of CheckBoxes for various status condition to generate an array [ 1, 0, 1, 1 ]<br />
to represent their on/off state. It also uses two combo boxes to filter by staff members<br />
as well as clients.</p>
<p>filterFunction:</p>

<div class="wp_codebox"><table><tr id="p2810"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
</pre></td><td class="code" id="p28code10"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> filterCases<span style="color: #66cc66;">&#40;</span>item:CaseVO<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">Boolean</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #808080; font-style: italic;">//is the item visible or hidden</span>
	<span style="color: #000000; font-weight: bold;">var</span> result:<span style="color: #0066CC;">Boolean</span> = <span style="color: #000000; font-weight: bold;">false</span>;
	<span style="color: #808080; font-style: italic;">//array of CheckBox.selected property values</span>
       <span style="color: #808080; font-style: italic;">// in handy ones and zeroes. This is returned from a function</span>
       <span style="color: #808080; font-style: italic;">// that takes the actual CheckBoxes as input and gives me this.</span>
	<span style="color: #000000; font-weight: bold;">var</span> case_mask:<span style="color: #0066CC;">Array</span> = <span style="color: #66cc66;">&#91;</span> <span style="color: #cc66cc;">1</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">1</span>, <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#93;</span>;
        <span style="color: #808080; font-style: italic;">//a couple VOs to verify the selectedItem in the ComboBoxes.</span>
	<span style="color: #000000; font-weight: bold;">var</span> client:PersonVO;
	<span style="color: #000000; font-weight: bold;">var</span> expert:PersonVO;
	<span style="color: #808080; font-style: italic;">//array iteration variable</span>
	<span style="color: #000000; font-weight: bold;">var</span> i:<span style="color: #0066CC;">int</span>;
&nbsp;
	<span style="color: #000000; font-weight: bold;">var</span> dateFormat:DateFormatter = <span style="color: #000000; font-weight: bold;">new</span> DateFormatter<span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#41;</span>
	dateFormat.<span style="color: #006600;">formatString</span> = <span style="color: #ff0000;">'MM/DD/YY'</span>
&nbsp;
	<span style="color: #808080; font-style: italic;">//text search</span>
	<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">caseNumInput</span>.<span style="color: #0066CC;">text</span>.<span style="color: #0066CC;">length</span> <span style="color: #66cc66;">&amp;</span>gt; <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">var</span> searchResult:<span style="color: #0066CC;">Boolean</span> = <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'0'</span> + item.<span style="color: #006600;">case_id</span>.<span style="color: #0066CC;">toString</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">search</span><span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">caseNumInput</span>.<span style="color: #0066CC;">text</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt;= <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span>
										<span style="color: #66cc66;">&#40;</span> item.<span style="color: #006600;">style</span>.<span style="color: #0066CC;">toLowerCase</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">search</span><span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">caseNumInput</span>.<span style="color: #0066CC;">text</span>.<span style="color: #0066CC;">toLowerCase</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt;= <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&#41;</span>  <span style="color: #66cc66;">&#41;</span>;
		<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> item.<span style="color: #006600;">description</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			searchResult = searchResult <span style="color: #66cc66;">||</span> <span style="color: #66cc66;">&#40;</span> item.<span style="color: #006600;">description</span>.<span style="color: #0066CC;">toLowerCase</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">search</span><span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">caseNumInput</span>.<span style="color: #0066CC;">text</span>.<span style="color: #0066CC;">toLowerCase</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt;= <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> item.<span style="color: #006600;">client_id</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			searchResult = searchResult <span style="color: #66cc66;">||</span> <span style="color: #66cc66;">&#40;</span> personProxy.<span style="color: #006600;">personFromId</span><span style="color: #66cc66;">&#40;</span> item.<span style="color: #006600;">client_id</span> <span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fullName</span>.<span style="color: #0066CC;">toLowerCase</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">search</span><span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">caseNumInput</span>.<span style="color: #0066CC;">text</span>.<span style="color: #0066CC;">toLowerCase</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt;= <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> item.<span style="color: #006600;">date_of_accident</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			searchResult = searchResult <span style="color: #66cc66;">||</span> <span style="color: #66cc66;">&#40;</span> dateFormat.<span style="color: #006600;">format</span><span style="color: #66cc66;">&#40;</span>item.<span style="color: #006600;">date_of_accident</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">search</span><span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">caseNumInput</span>.<span style="color: #0066CC;">text</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt;= <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span> i = <span style="color: #cc66cc;">0</span>; i <span style="color: #66cc66;">&amp;</span>lt; case_mask.<span style="color: #0066CC;">length</span>; i++ <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">client</span>.<span style="color: #006600;">selectedItem</span> is PersonVO <span style="color: #66cc66;">&#41;</span>
			<span style="color: #66cc66;">&#123;</span>
				client = caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">client</span>.<span style="color: #006600;">selectedItem</span>
&nbsp;
				<span style="color: #808080; font-style: italic;">//is an expert selected for filtering also?</span>
				<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">expert</span>.<span style="color: #006600;">selectedItem</span> is PersonVO <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; searchResult<span style="color: #66cc66;">&#41;</span>
				<span style="color: #66cc66;">&#123;</span>
					expert = caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">expert</span>.<span style="color: #006600;">selectedItem</span>;
					<span style="color: #808080; font-style: italic;">//filter for client, expert, and status</span>
					<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>case_mask<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #0066CC;">status</span> == <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> i + <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
							<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #006600;">client_id</span> == client.<span style="color: #006600;">id</span>
							<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #006600;">expert_id</span> == expert.<span style="color: #006600;">id</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; searchResult  <span style="color: #66cc66;">&#41;</span>
						result = <span style="color: #000000; font-weight: bold;">true</span>;
				<span style="color: #66cc66;">&#125;</span>
				<span style="color: #b1b100;">else</span>
				<span style="color: #66cc66;">&#123;</span>
					<span style="color: #808080; font-style: italic;">//filter for client and status</span>
					<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>case_mask<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #0066CC;">status</span> == <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> i + <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
							<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #006600;">client_id</span> == client.<span style="color: #006600;">id</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; searchResult  <span style="color: #66cc66;">&#41;</span>
						result = <span style="color: #000000; font-weight: bold;">true</span>;
				<span style="color: #66cc66;">&#125;</span>
			<span style="color: #66cc66;">&#125;</span>
			<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">expert</span>.<span style="color: #006600;">selectedItem</span> is PersonVO <span style="color: #66cc66;">&#41;</span>
			<span style="color: #66cc66;">&#123;</span>
				expert = caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">expert</span>.<span style="color: #006600;">selectedItem</span>;
				<span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span> i = <span style="color: #cc66cc;">0</span>; i <span style="color: #66cc66;">&amp;</span>lt; case_mask.<span style="color: #0066CC;">length</span>; i++ <span style="color: #66cc66;">&#41;</span>
				<span style="color: #66cc66;">&#123;</span>
					<span style="color: #808080; font-style: italic;">//filter for expert and status</span>
					 <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>case_mask<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #0066CC;">status</span> == <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> i + <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
					 		<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #006600;">expert_id</span> == expert.<span style="color: #006600;">id</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; searchResult  <span style="color: #66cc66;">&#41;</span>
					 	result = <span style="color: #000000; font-weight: bold;">true</span>
				<span style="color: #66cc66;">&#125;</span>
&nbsp;
			<span style="color: #66cc66;">&#125;</span>
			<span style="color: #b1b100;">else</span>
			<span style="color: #66cc66;">&#123;</span>
				<span style="color: #808080; font-style: italic;">//filter for client and status</span>
				<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>case_mask<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #0066CC;">status</span> == <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> i + <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
						<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; searchResult  <span style="color: #66cc66;">&#41;</span>
					result = <span style="color: #000000; font-weight: bold;">true</span>;
			<span style="color: #66cc66;">&#125;</span>
		<span style="color: #66cc66;">&#125;</span>
	<span style="color: #66cc66;">&#125;</span>
	<span style="color: #808080; font-style: italic;">//see if a client is selected for filtering</span>
	<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">client</span>.<span style="color: #006600;">selectedItem</span> is PersonVO <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		client = caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">client</span>.<span style="color: #006600;">selectedItem</span>
		<span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span> i = <span style="color: #cc66cc;">0</span>; i <span style="color: #66cc66;">&amp;</span>lt; case_mask.<span style="color: #0066CC;">length</span>; i++ <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			<span style="color: #808080; font-style: italic;">//is an expert selected for filtering also?</span>
			<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">expert</span>.<span style="color: #006600;">selectedItem</span> is PersonVO <span style="color: #66cc66;">&#41;</span>
			<span style="color: #66cc66;">&#123;</span>
				expert = caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">expert</span>.<span style="color: #006600;">selectedItem</span>;
				<span style="color: #808080; font-style: italic;">//filter for client, expert, and status</span>
				<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>case_mask<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #0066CC;">status</span> == <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> i + <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
						<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #006600;">client_id</span> == client.<span style="color: #006600;">id</span>
						<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #006600;">expert_id</span> == expert.<span style="color: #006600;">id</span>  <span style="color: #66cc66;">&#41;</span>
					result = <span style="color: #000000; font-weight: bold;">true</span>;
			<span style="color: #66cc66;">&#125;</span>
			<span style="color: #b1b100;">else</span>
			<span style="color: #66cc66;">&#123;</span>
				<span style="color: #808080; font-style: italic;">//filter for client and status</span>
				<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>case_mask<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #0066CC;">status</span> == <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> i + <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
						<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #006600;">client_id</span> == client.<span style="color: #006600;">id</span>  <span style="color: #66cc66;">&#41;</span>
					result = <span style="color: #000000; font-weight: bold;">true</span>;
			<span style="color: #66cc66;">&#125;</span>
		<span style="color: #66cc66;">&#125;</span>
	<span style="color: #66cc66;">&#125;</span>
	<span style="color: #808080; font-style: italic;">//client isn't selected, check the expert filter.</span>
	<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">expert</span>.<span style="color: #006600;">selectedItem</span> is PersonVO <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		expert = caseGrid.<span style="color: #006600;">filter</span>.<span style="color: #006600;">expert</span>.<span style="color: #006600;">selectedItem</span>;
		<span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span> i = <span style="color: #cc66cc;">0</span>; i <span style="color: #66cc66;">&amp;</span>lt; case_mask.<span style="color: #0066CC;">length</span>; i++ <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			<span style="color: #808080; font-style: italic;">//filter for expert and status</span>
			 <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>case_mask<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #0066CC;">status</span> == <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> i + <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
			 		<span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #006600;">expert_id</span> == expert.<span style="color: #006600;">id</span>  <span style="color: #66cc66;">&#41;</span>
			 	result = <span style="color: #000000; font-weight: bold;">true</span>
		<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #66cc66;">&#125;</span>
	<span style="color: #808080; font-style: italic;">//finally, filter for the status</span>
	<span style="color: #b1b100;">else</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span> i = <span style="color: #cc66cc;">0</span>; i <span style="color: #66cc66;">&amp;</span>lt; case_mask.<span style="color: #0066CC;">length</span>; i++ <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			<span style="color: #808080; font-style: italic;">//filter for status</span>
			<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> case_mask<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&amp;</span>amp;<span style="color: #66cc66;">&amp;</span>amp; item.<span style="color: #0066CC;">status</span> == <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> i + <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
				result = <span style="color: #000000; font-weight: bold;">true</span>;
		<span style="color: #66cc66;">&#125;</span>
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> result
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>You can see that I am repeating myself from the top down to the final else statement, cutting the filter parameters down like a layer cake. It works, and is relatively quick on a grid with 1500 or so items. This just screams "<strong>REFACTOR ME</strong>" every time I see it.</p>
]]></content:encoded>
			<wfw:commentRss>http://joelhooks.com/2008/03/14/complex-datagrid-filterfunction-in-flexair/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Maximizing your AIR application programatically &#8211; stage.nativeWindow.maximize()</title>
		<link>http://joelhooks.com/2008/01/10/stagenativewindowmaximize-maximizing-your-air-application-programatically/</link>
		<comments>http://joelhooks.com/2008/01/10/stagenativewindowmaximize-maximizing-your-air-application-programatically/#comments</comments>
		<pubDate>Thu, 10 Jan 2008 21:11:10 +0000</pubDate>
		<dc:creator>Joel</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[actionscript]]></category>

		<guid isPermaLink="false">http://joelhooks.com/?p=7</guid>
		<description><![CDATA[Just be sure to call it in an applicationComplete handler. My attempts to call it from creationComplete were resulting in a null object reference. 1 stage.nativeWindow.maximize()]]></description>
			<content:encoded><![CDATA[<p>Just be sure to call it in an applicationComplete handler. My attempts to call it from creationComplete were resulting in a <em>null</em> object reference.</p>

<div class="wp_codebox"><table><tr id="p712"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p7code12"><pre class="actionscrpt" style="font-family:monospace;">stage.nativeWindow.maximize()</pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://joelhooks.com/2008/01/10/stagenativewindowmaximize-maximizing-your-air-application-programatically/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
	</channel>
</rss>
