<?xml version="1.0" encoding="UTF-8"?>
<posts type="array">
  <post>
    <body>_This post follows on from a series on architecting a basic PureMVC application. Well, it's actually the final brief installment, and at the same time a completely separate post, as the view and model classes in a PureMVC app should have no knowledge of the framework itself. So if you don't know or care for PureMVC you're in luck - this post just outlines a very simple approach to creating a tag cloud in Flex._

I recently put together a simple tag cloud (is there any other kind?) in Flex. Unsurprisingly others have come up with approaches to constructing a tag cloud in Flex, including "Buttons and FlowBoxes":http://www.glodde.com/blog/default.aspx?id=1&amp;t=Basic-Flex-TagCloud-Component. All perfectly reasonable, but I thought there was no harm in just relying on a humble textfield to do the work.

So to achieve this, I have a @TagCloudView@ class, whose one important method is @setData@:

&lt;code lang="actionscript"&gt;
public function setData( tagCloudData:TagCloudData ):void
{
        var html:String = "";
        var size:uint = MIN_SIZE;
        var step:Number = ( MAX_SIZE - MIN_SIZE ) / tagCloudData.range;
        var tags:ArrayCollection = tagCloudData.sortAndReturnTags();

        var i:uint = 0;
        var l:uint = tags.length;

        for (; i &lt; l; i++)
        {
                var tag:Tag = Tag ( tags[i] );
                size = Math.round( MIN_SIZE + ( (tag.count - tagCloudData.min) * step ) );
                html += "&lt;a href=\"event:"
                     + tag.name
                     + "\"&gt;&lt;font size=\""
                     + size
                     + "\"&gt;"
                     + tag.name
                     + "&lt;/font&gt;&lt;/a&gt; ";
        }
        content.htmlText = html;
}
&lt;/code&gt;
The minimum and maximum font sizes for this tag cloud are constants defined within the class, which are used to calculate the step between each font size to be used in the tag cloud. We need to work out the range of occurrences for each term (and the min and max occurrences), which the tagCloudData model does for us. It also sorts the tags alphabetically and returns an ArrayCollection we can loop through:
&lt;code lang="actionscript"&gt;
public function sortAndReturnTags():ArrayCollection
{
        var sort:Sort = new Sort();
        sort.fields = [ new SortField("name", false) ];
        tags.sort = sort;
        tags.refresh();
        return tags;
}
&lt;/code&gt;
Getting back to the setData method you can see the method simply loops through the tags within the data object to construct a string of html links. Each link href can be prefixed with 'event:' to trigger a "link TextEvent":http://livedocs.adobe.com/flex/3/langref/flash/text/TextField.html#event:link so the action can be handled within the player, or alternatively it can call a url as normal. The font size is calculated by setting it to the minimum size specified, and then adding additional steps for any number of occurrences over the minimum.

That's all there really is to it. All the code, which includes the basic PureMVC application code from the previous posts, is available "here":http://www.experimeme.net/code/flex/tag-cloud.zip</body>
    <created-at type="datetime">2008-12-17T23:31:37Z</created-at>
    <ham-comments-count type="integer">0</ham-comments-count>
    <id type="integer">31</id>
    <permalink>flex-tag-cloud-example</permalink>
    <title>Flex Tag Cloud Example</title>
    <updated-at type="datetime">2010-01-16T12:55:54Z</updated-at>
  </post>
  <post>
    <body>The "Proxy":http://en.wikipedia.org/wiki/Proxy_pattern is used throughout PureMVC to access model data. Proxies are registered with the facade, and then retrieved when required by other proxies, commands, and mediators whenever data needs to be accessed. Proxies broadcast notifications when a change to model state occurs, but do not listen for notifications.

Previously we registered two proxies for the data of interest to this application, the FlashVarsProxy and the RemoteProxy. The FlashVarsProxy is self-explanatory and trivial, so we'll move our focus on to the RemoteProxy. In this example tag cloud app we only have one remote service, so we define and set the service within the RemoteProxy class itself. (For larger applications you'd want to create a service class that can be shared across proxies.)

As we're using the MultiCore version of PureMVC we must do this in an overridden @onRegister@ method to avoid any "Error: multitonKey for this Notifier not yet initialized!". It sounds overly complex but it isn't - MultiCore just lets you run multiple versions of the framework at the same time, and even if you're not after the additional capabilities it's sensible to use MultiCore by default. If you'd like more details on the two options "this blog post":http://lowpitch.com/blog/puremvc-multicore-vs-standard-singlecore/ is worth reading. Anyway, onto some code:
&lt;code lang="actionscript"&gt;
override public function onRegister():void
{   
        var gateway:String = flashVarsProxy.gateway;

        var service:RemoteObject = new RemoteObject();

        var channelSet:ChannelSet = new ChannelSet();
        var amfChannel:Channel = new AMFChannel( "rubyamf", gateway );
        channelSet.addChannel( amfChannel );
        service.destination = "rubyamf";
        service.source = "PostsController";
        service.channelSet = channelSet; 

        var responder:Responder = new Responder( getTagsResult, getTagsFault );
        var call:AsyncToken = service.tag_counts();
        call.addResponder(responder);
}
&lt;/code&gt;
Flex allows you to define services in a services.config xml file, but at least in this instance I prefer doing it directly in ActionScript. I'm using RubyAMF to connect to my PostsController and get the tag information as you can see above. Once the service returns a result, it will call our @getTagsResult@ method:
&lt;code lang="actionscript"&gt;
public function getTagsResult( e:ResultEvent ):void
{
        _tagCloudData = new TagCloudData();

        for each ( var tag:Tag in e.result )
        {
                _tagCloudData.addTag( tag );
        }

        sendNotification( Notify.TAGS_LOADED );
}
&lt;/code&gt;
The _tagCloudData instance variable is our actual model. If this weren't a toy app, you'd most probably have a TagCloudDataProxy which wrapped around it and was used throughout the application to access the model.

Best practice (not always reflected in the PureMVC site examples) dictates that you keep thin proxies. That is to say both the model and proxy should implement the same interface, and a proxy should merely delegate calls to the model and send notifications when appropriate. That way your domain logic stays entirely within the model, which makes it transportable and easier to unit test (very much like the view - if you see any imports from the org.puremvc namespace in your model classes you're doing it wrong).

This wraps up the basic architecture of a PureMVC application. It's a little overkill for something as straightforward as a tag cloud (which I can already generate automatically via rails) but illustrates the basic application flow and architecture which forms the basis of all PureMVC applications.

Coming at PureMVC fresh it might seem like an overly-complex, possibly invasive framework, but the opposite is true. You register Commands, Proxies, and Mediators, use Notifications to communicate, and your model and view are completely separate from the framework itself. Because of this, I'll hold off on talking through the TagCloudView and TagCloudData till the next post.</body>
    <created-at type="datetime">2008-12-12T23:04:01Z</created-at>
    <ham-comments-count type="integer">0</ham-comments-count>
    <id type="integer">29</id>
    <permalink>basic-architecture-of-a-puremvc-application-part-iii</permalink>
    <title>Basic Architecture of a PureMVC Application: Part III</title>
    <updated-at type="datetime">2008-12-12T23:33:47Z</updated-at>
  </post>
  <post>
    <body>In PureMVC, the "Mediator":http://en.wikipedia.org/wiki/Mediator_pattern design pattern is used to mediate between the view and the framework. This reduces coupling, as the view knows nothing about the framework (if you're importing any org.puremvc classes into your view, you're doing it wrong), and knowledge of the view's public API is limited to the Mediator which manages it. To kick things off we pass the view component to the Mediator, and register it with the framework:
&lt;code lang="actionscript"&gt;
public class ViewPrepCommand extends SimpleCommand
{
	facade.registerMediator( new TagCloudViewMediator( new TagCloudView ) );
}
&lt;/code&gt;

The Mediator itself should provide limited functionality. It should advertise which notifications it's interested in (via its listNotifications method, which is queried when the Mediator is registered via the facade), and respond to those same notifications by manipulating the view it mediates for. For instance, in our tag cloud example, we want to know when data about the tags has been received, and then retrieve this data from the relevant proxy and pass it to the view:
&lt;code lang="actionscript"&gt; 
override public function listNotificationInterests():Array
{   
    return [ Notify.TAGS_LOADED ];
}   

override public function handleNotification( note:INotification ):void
{   
    var name:String = note.getName();

    switch( name )
    {   
        case Notify.TAGS_LOADED:
            view.setData( getTags() );
           break;
    }   
}   

private function getTags():Array
{   
    return remoteProxy.getTags();
}   

private function get view():TagCloudView
{   
    return TagCloudView( viewComponent );
}

private function get remoteProxy():RemoteProxy
{
    return facade.retrieveProxy( RemoteProxy.NAME ) as RemoteProxy;
}
&lt;/code&gt;

As you run through this example, you'll see that there isn't much to our TagCloudMediator. That should be true of most mediators, if you find yours are much heavier than this or rely on a variety of private setup functions you should seriously consider moving this application logic to a command. We've already touched on the @listNotificationInterests@ method, so moving on you can see that the @handleNotification@ method determines how to act based on the name of the notification. In our case we're only interested in Notify.TAGS_LOADED, and once this occurs, we pass the relevant data to the view.

One style we've settled on is to use an implicit getter called view() to cast the viewComponent Object to the specific type and return it. 'tagCloudView' is perhaps more descriptive, but there are certainly benefits in only having to locate and parse 'view' as you work across multiple mediators within an application.

You'll notice we get tags via the RemoteProxy, so it's a good time to back up, and look at the @ModelPrepCommand@ we skipped over a little earlier:
&lt;code lang="actionscript"&gt;
    public class ModelPrepCommand extends SimpleCommand
    {   
        override public function execute( notification:INotification ):void
        {   
            super.execute( notification );
            facade.registerProxy( new FlashVarsProxy( Application.application.parameters ) );
            facade.registerProxy( new RemoteProxy() );
        }   
    }   
}
&lt;/code&gt;
Here we register two proxies: a new FlashVarsProxy, which is used to store and return any variables set on the swf file from within the html, and a RemoteProxy, which is reasonably straightforward. We're calling it the @RemoteProxy@ because in this simple example it is the one and only proxy for accessing remote data. In the next post I'll run through our RemoteProxy in detail.</body>
    <created-at type="datetime">2008-12-09T21:28:14Z</created-at>
    <ham-comments-count type="integer">0</ham-comments-count>
    <id type="integer">28</id>
    <permalink>basic-architecture-of-a-puremvc-application-part-ii</permalink>
    <title>Basic Architecture of a PureMVC Application: Part II</title>
    <updated-at type="datetime">2009-04-21T07:24:36Z</updated-at>
  </post>
  <post>
    <body>I previously went through setting up a RubyAMF gateway to provide AMF responses, and the next step was to build a Rich Client to consume this service. A simple tag cloud on its own does not demand the overhead of a framework, but explaining how to use a framework sensibly is often suited to simple examples, so that's how we'll start.

If you haven't used PureMVC before, I'd recommend visiting "http://www.puremvc.org":http://www.puremvc.org and reading through the excellent "Best Practices":http://puremvc.org/component/option,com_wrapper/Itemid,174/ [pdf] documentation. The following notes should reflect some of these best practices along with some we've settled on at LBi.

Our app, like all PureMVC apps, will begin with the @ApplicationFacade@. Based on the "Facade":http://en.wikipedia.org/wiki/Facade_pattern design pattern, the name already gives an indication of its purpose. In the case of PureMVC, the @ApplicationFacade@ provides a single interface to work with the core Model, View, and Controller actors without a developer having to worry about dealing with them directly. Once we instantiate the @ApplicationFacade@ in the main class we call its startup method which sends a Notify.STARTUP notification to kick the app into life:
&lt;code lang="actionscript"&gt;
public function startup( app:* ):void
{
	sendNotification( Notify.STARTUP, app );
}
&lt;/code&gt;

The Notification system within PureMVC is based on the "Observer":http://en.wikipedia.org/wiki/Observer_pattern design pattern, and is a straightforward approach to enabling commmunication between the various actors within the framework. We prefer to define @Notification@ constants in a separate Notify class instead of directly within the @ApplicationFacade@, and in a more complex application you might want to think about logically breaking notifications into separate classes, and in the case of Models, defining them on the associated Proxies which send the Notifications (more on this later).

The Notify.STARTUP Notification triggers activity because in the same @ApplicationFacade@ class we've mapped this particular notification to a specific Command:

&lt;code lang="actionscript"&gt;
override protected function initializeController():void
{
	super.initializeController();
	registerCommand( Notify.STARTUP, StartupCommand );
&lt;/code&gt;

The "Command":http://en.wikipedia.org/wiki/Command_pattern design pattern involves creating stateless objects which execute actions in response to specific events. PureMVC provides both simple commands, which have an @execute@ method, and macro commands, which list a number of simple commands which should be executed in order. Because a number of commands may be required at application startup,  StartupCommand is defined as a macro command:
&lt;code lang="actionscript"&gt;
public class StartupCommand extends MacroCommand
{
	override protected function initializeMacroCommand():void
	{
		addSubCommand( ModelPrepCommand );
		addSubCommand( ViewPrepCommand );
	}
}
&lt;/code&gt;

I'll detail how these commands are used in the next post.</body>
    <created-at type="datetime">2008-12-09T20:47:09Z</created-at>
    <ham-comments-count type="integer">0</ham-comments-count>
    <id type="integer">27</id>
    <permalink>basic-architecture-of-a-puremvc-application-part-i</permalink>
    <title>Basic Architecture of a PureMVC Application: Part I</title>
    <updated-at type="datetime">2008-12-09T21:38:43Z</updated-at>
  </post>
  <post>
    <body>As I've "previously mentioned":http://www.experimeme.net/rubyamf-currently-breaks-rspec-tests, RubyAMF gives you @render:amf@ so you can send controller responses as binary AMF streams to Flash / Flex applications (also known as Flash remoting).

Setting it up for rails is reasonably straightforward. You just need to @script/install http://rubyamf.googlecode.com/svn/trunk/rubyamf@ to install the plugin. If you're developing locally you'll want to restart your webserver, and then you should be able to browse to http://localhost:3000/rubyamf_gateway/ which will return an http response with a logo of RubyAMF.

Once that's done the class mappings need to be specified, so that (for instance) a Tag class in ActionScript returned by a client swf is automatically deserialised into the appropriate Tag class within the Rails application.

Over a few posts I'm going to demonstrate putting together a Flex-based tag cloud which uses RubyAMF, so the mapping (which is defined in @config/rubyamf_config.rb@) would be this:

&lt;code lang="ruby"&gt;
ClassMappings.register(:actionscript =&gt; 'Tag', :ruby =&gt; 'Tag', :type =&gt; 'active_record',
:attributes =&gt; ["id", "name", "count"])
&lt;/code&gt;

(There's plenty of examples in the config file along with other options worth looking at.)

Once that's defined you'll want to specify a controller method which returns your tag cloud data and also responds to AMF requests. As I "mentioned earlier":http://www.experimeme.net/adding-tagging I'm using "acts_as_taggable_on_steroids":http://agilewebdevelopment.com/plugins/acts_as_taggable_on_steroids at the moment, and this plugin gives me a method which returns all tags and their counts, so the method (defined in my @posts_controller.rb@ file) is as simple as this:
&lt;code lang="ruby"&gt;
def tag_counts
	@tags = Post.tag_counts
	respond to do |format|
		format.html # If you'd like to do something in html
		format.amf { render:amf =&gt; @tags }
	end
end
&lt;/code&gt;

At this point you'll have an AMF gateway and a method which will return a complex datatype serialised as AMF. The next step is to build a Rich Client in Flex to consume this service.</body>
    <created-at type="datetime">2008-11-30T17:31:46Z</created-at>
    <ham-comments-count type="integer">0</ham-comments-count>
    <id type="integer">26</id>
    <permalink>setting-up-rubyamf-for-flash-and-flex</permalink>
    <title>Setting up RubyAMF for Flash and Flex</title>
    <updated-at type="datetime">2008-12-08T00:06:08Z</updated-at>
  </post>
  <post>
    <body>Yes it works, but on OSX there's a potential Java hitch to be aware of.

Download "Eclipse Ganymede 3.4":http://www.eclipse.org/downloads/. Unzip Eclipse to a directory (normally Applications).

Download "Flex Builder 3.01 Plugin":https://www.adobe.com/cfusion/tdrc/index.cfm?loc=en_us&amp;product=flex_eclipse.

*BEFORE* you run the Flex Builder Plugin installer on OSX, check that your java version is set to 1.5. However a simple @java -version@ is not enough to satisfy the installer. You also have to @cd /System/Library/Frameworks/JavaVM.framework/Versions/@ and @ls -al@ to check that CurrentJDK -&gt; 1.5.0.

I'd previously installed Java 1.6 on Mac, and although @java -version@ gave me 1.5, the CurrentJDK -&gt; 1.6.0. This seems to have caused my install to fail with the error: 'This installation can still be configured manually as a Product Extension' and soon after an alert with 'a newer file named "com.adobe.flexbuilder.debug.e33_3.0.205647.jar" already exists at "/Applications/Adobe Flex Builder 3 Plug-in/eclipse/plugins" Do you want to overwrite this file?' Trying to follow the instructions offered is a fruitless exercise I won't bother recounting because "someone else already has":http://www.newviewnetworks.com/nvnhome/blog/client/?p=103 (Borg - no permalinks for comments on that site).

Anyway ensuring you have 1.5.0 all the way should guarantee a successful install.</body>
    <created-at type="datetime">2008-11-18T16:45:27Z</created-at>
    <ham-comments-count type="integer">0</ham-comments-count>
    <id type="integer">25</id>
    <permalink>flex-builder-3-01-plugin-in-eclipse-ganymede-3-4-on-osx</permalink>
    <title>Flex Builder 3.01 Plugin In Eclipse Ganymede 3.4 on OSX</title>
    <updated-at type="datetime">2008-11-18T17:06:09Z</updated-at>
  </post>
</posts>
