Monthly Archive for November, 2007

My Flex-based Chart Engine

I've been looking for a good charting mechanism for a few personal apps.   CFCHART works in some cases, but I usually opt for SVG, either rendered inline (i.e. SVG and XHTML interleaved in an XML doc) or rasterized into a PNG server-side via Batik.  Both solutions have their merits, but both also have a lot of problems (drawing SVG requires a lot of arcane math, and CFCHART is quite inflexible and has a number of bugs).

At work, I've been doing quite a bit of work with the Flex Charting components, and I got to thinking that a generic chart that could be parameterized with both data and structure wouldn't be too hard to build, but never really did anything about it.  Then today Koen, Joshua, and I were talking about something or other and somehow ended up with me mentioning you could inline your MXML with a JSP taglib and have a Flex movie spit out in your page (much as CFCHART does it).  I threw together a little proof of concept, and digging in a little deeper with flashvar parameterization, realized that you could do some pretty sweet stuff with it.

I kept playing a bit, and started building some generic charting stuff, and this is what I ended up with.  It takes a descriptor XML document either as a literal or a URL, supplied via flashvars or via ExternalInterface callbacks, and will draw a chart based on it.  The descriptor is just that, a complete description of the chart to render, both data and structure.  There's a link to the descriptor on the demo page, so you can see it.  The flexibility is pretty limited (for example, you can't disable the legend), but all that stuff would be pretty simple to add down the road.

The engine only supports Cartesian charts, and only numeric data (linear or logarithmic), but that covers the vast majority of charts, at least for me.  It'd be fairly trivial to extend it to support category and/or datetime axes, I just didn't do it.  The non-Cartesian charts (e.g. pie charts) would be a little more work, as they're pretty fundamentally different, but it should be a backwards compatible change (i.e. strictly additive changes to the descriptor language).

I've made a ZIP of the demo app, including the custom tag wrapper and the MXML source.  For the runtime compilation via the JSP taglib, you have to have Flex on your server.  If you've got CF8 with LCDS, you're set.  I'm not sure about other configurations, but I know the JSP taglib has been around for a while, so I'd expect it to work other places as well (though you might need to tweak).

The runtime compilation is not at all required for the engine to work, it's just an easy way to package it because the taglib takes care of generating all the wrapper HTML/JS.  If you don't mind writing that yourself, you can use the SWF directly.

Also, the SWF is compiled with Flex SDK 2.0.1, because that's what CF's LCDS uses.  Among other things, that means you don't get "grouped" ColumnSets, because those are new in Flex 3.  The MXML will recompile as-is with SDK 3 (e.g. in FlexBuilder), and then you'll be able to use "grouped", but the runtime compilation won't do that unless you upgrade the internal SDK.

Schema Tool Update

I've updated my schema tool again, this time with some pretty significant changes.  Quick recap: the goal of the app is to manage your DB schema via managed code, rather than some external process, so you get transparent database upgrade to all environments as part of deploying a new version of your app.  Very handy in production, essential in development.

Here's a rundown of what's new:

  • Multiple tool types are now supported via a new 'toolfactory' CFC.  The original "database" tool has been joined by a new filesystem tool that stores it's version info in a file, rather than a database.  If you want to use the migration infrastructure for something outside a database (like your CF Admin config via the admin API) you can now do it with no database dependency using the filesystem tool.
  • The 'tool' CFC has been deprecated, in favor of 'databasetool'.  Note that with the new multi-tool arrangement, the order of init parameters has changed (since they're now passed to 'toolfactory' not the tool directly), so watch out when you're upgrading.
  • SQL-based migrations (where you use a SQL file instead of a CFC) are now a lot safer.  The original minor version computations made some assumptions about the scripts that were "mostly" safe, but not completely.  I've improved the parsing significantly (reusing some code from the Rhino project) to do string stripping/replacement, and support both — and /* */ comments.
  • This is entirely internal, but the organization of components has been much improved.  There was a lot of non-encapsulation in there originally, but I've fixed most of that, as well as done some more abstraction to get some additional logic reuse, especially across different tools.

Assuming you haven't gone hacking the core, nor subclassed 'abstractmigration' and overridden 'init', you should be able to migrate simply by replacing the line in Application.cfm that runs the tool.  Instead of creating a tool directly and invoking it, you now use the 'toolfactory' to create your tool implicitly, and then invoke it.  The demo app has an example.  It also has an example of a filesystem tool, with separate migration script directories for each tool to manage.

A ZIP is available here, or you can browse the Subversion repository directly.  As always, comments/questions/bugs are welcome and appreciated.

Excalibur Constants

I believe I've blogged about Excalibur (an RPN calculator for Win32) before, but I just discovered the wide array of constants that it has built in:

Excalibur Constants

While I can't say that I use many of those numbers in my daily calculations (which are usually either pixels or dollars), the last one is definitely useful.

Regular Expression Backreferences and the Non-Greedy Modifier

Update: James Allen caught a formatting bug. It seems WordPress doesn't like my coloring, and when present, swaps the double quotes for "smart quotes". I've removed the coloring, and it seem to be fine again.

Someone posted a question on CF-Talk about using backreferences in regular expression search strings. Not the replacement string, mind you, but the search string itself. This is, as you'd expect, perfectly legal and can be incredibly powerful. While contriving an example, the one I came up with also required the non-greedy modifier, so I'll illustrate both. Here's the code in question (copy it to a CFM file to run it):

<cfoutput>
<cfset baseString = "some 'text' with ""quotes an' some apostrophes"" in it" />
<h2>Quoted Strings within #baseString#</h2>
<ul>
<cfset start = 1 />
<cfloop condition="true">
  <cfset result = REFind("(['""])(.*?)\1", baseString, start, true) />
  <cfif result.pos[1] LT 1>
    <cfbreak />
  </cfif>
  <cfset string = mid(baseString, result.pos[3], result.len[3]) />
  <cfset quote = mid(baseString, result.pos[2], result.len[2]) />
  <cfset start = result.pos[1] + result.len[1] />
  <li>#string# (quoted with #quote#)</li>
</cfloop>
</ul>
</cfoutput>

The backreference (the "\1" at the end of the regex) behaves exactly the same as when in a replacement string: it represents the "stuff" matched by the first clause wrapped in parentheses (in this case, "['""]"). Ignoring the middle part, the regex says find me either a single or double quote, then some "stuff", and then the same quote character.

In the middle is the non-greedy modifier (the "?", after the asterisk). Without it the ".*" would match as much as possible while still allowing the regex as a whole to succeed. In this specific case, the quote would match the single-quote before "text", the .* would match "text with "quotes an", and then the backreference would match the single-quote after "an". That's clearly not what we want, so we use the non-greedy operator to tell the .* that we only want it to match as much as it needs to, not as much as it can. Then it behaves correctly. Try deleting the non-greedy modifier and run it.

Enums and ActionScript's Static Initializers

I discovered today, while trying to synthesize an Enum type, that AS3 has the concept of a static initializer, which is awesome. In a nutshell, a static initializer is kind of like a constructor, but it's for the class object itself, not instances of the class. It gets invoked during classloading, after all static properties have been set, but the class is turned loose for general consumption. Here's an example of an Enum type (named ColorEnum) that uses the static initializer (in bold):

package com.barneyb.test {

  public class ColorEnum {

    public static const BLACK:ColorEnum = new ColorEnum(0x000000);
    public static const WHITE:ColorEnum = new ColorEnum(0xFFFFFF);

    private static var locked:Boolean = false;

    {
      locked = true;
    }

    private var _color:uint;
    public function get color():uint {
      return _color;
    }

    public function ColorEnum(color:uint) {
      if (locked) {
        throw new Error("You can't instantiate ColorEnum");
      }
      _color = color;
    }
  }
}

What this provides is a ColorEnum class that cannot be instantiated, with two instances stored in the BLACK and WHITE static constants. This sort of class locking is equally useful for singletons (think ServiceLocator if you use Cairngorm, though they implement it differently). Usually, you use a private constructor for this type of behaviour, but since AS3 doesn't support that, you have to synthesize it. However, that's not all a static initializer can do.

Another use case is if you have a complex static variable that you need to initialize, but can't do in a single expression. For example, if you need to create multiple aggregated objects, you usually need multiple expressions. You can do this in a static initializer as well. Note that you can't set a static const within a static initializer, but you can set a static var (variables).

It's November…

… and that means NaBloPoMo, and this counts.