Friday, May 16, 2008

Java SwingBuilder: turbo-charging YAML with virtual constructor flow

I *was* supposed to look into integrating Commons Validators into the JavaBuilder concept, but occasionally one had that flash of inspiration where for a moment you cross into "mad scientist" territory...and this week had one of those. I've added a new concept to YAML that I call "virtual constructor flow" that basically compacts the file format to the maximum level allowed by natural law. :-)

OK, but let's start from the beginning. Let's say we have a typical builder file like this in YAML, with the traditional YAML white-space indentaton to indicate hierarchy:

JFrame:
name: myFrame
title: My App Frame
state: max

YAML supports the concept of alternate flows, hence the same data can be expressed in-line, which basically turns a portion of it into JSON:

JFrame: {name: myFrame, title: My App Frame, state: max}

This is very cool and it helps to reduce the number of lines in a file. However, it does not work if the node in question has additional child nodes. In Java SwingBuilder, by convention children are grouped under the "content" list node (same name as in JavaFX...not a coincidence, obviously):

JFrame:
name: myFrame
title: My App Frame
state: max
content:
- JPanel:
name: mainPanel
content:
- JButton: {name: okButton, text: OK}

The limitation / design (?) of YAML is that once you escape into the JSON format the entire child node has to be expressed in it, even if it has children of its own. This unfortunately would lead to many nested "{", "}", "[", "]" brackets (if you've seen any serious JavaFX code, you will see it often has lots of secton with 10 or more levels of nested brackets of various type).

So, if I wanted to cut down on the number of lines in a file and do it all inline it loses all the nice, clear YAML whitespace indentation and descends into JSON closing bracket hell:

JFrame: {name: myFrame, title: My App Frame, state: max, content: [
{JPanel: {name: mainPanel, content: [
{JButton: {name: okButton, text: OK}}
]}
]}


In other complex file very soon you will have multiple levels of nested "}]}" type closing brackets, which makes it very unreadable IMHO. That's why I opted for YAML instead of JSON.

What I would like to do is to use the in-line formats for the properties belonging to the current node and then go back to regular white-space YAML for its children, e.g.:

JFrame: {name: myFrame, title: My App Frame, state: max}
content:
- JPanel: {name: mainPanel}
content:
- JButton: {name: okButton, text: OK}


However, this is not allowed in YAML and the YAML parsing library will exit with an exception. It's all whitespace or it's all JSON-style brackets, but you can't mix and match them.

So, this is where the mad scientist mode entered. I decided to add a new flow type to YAML via a custom preprocesor that I call "virtual constructor flow" and it looks like this:

JFrame(name=myFrame, title=MyAppFrame, state=max):
content:
- JPanel(name=mainPanel):
content:
- JButton(nam=okButton, text=OK)

This is still valid YAML (it gets processed without errors), but obviously the child properties are now embedded directly into the YAML node definition, so it does not know about them, it just sees a node defined as JFrame(name=myFrame, title=MyAppFrame, state=max)

The JB pre-processor will take the YAML Object and do a second pass through and "explode" those properties embedded int the virtual constructor flow and create at run-time the exact same "pure" YAML hierarchy as seen at the beginning.

Also, the pre-processor does some nifty stuff such as if a node is defined right off the bat as a list (e.g. "JFrame: " with "- JButton", "- JLabel" nods underneath it) it will property "move" the list one level down to the default "content" node.

Therefore all we have left is:

JFrame(name=myFrame, title=MyAppFrame, state=max):
- JPanel(name=mainPanel):
- JButton(nam=okButton, text=OK)

A lot less than the original input:

JFrame:
name: myFrame
title: My App Frame
state: max
content:
- JPanel:
name: mainPanel
content:
- JButton: {name: okButton, text: OK}

but at run-time the pre-processor will "explode" the compressed format to exactly the same thing.

Now you are wondering, "well OK, this is cool, but is it really worth it to bastardize YAML with some sort of custom extension?". And the answer is YES, it is worth, 'cause it brings amazing reduction in the size and levels of indentation when defining UIs via Java SwingBuilder.

Let's say we have a simple JFrame with 3 main menus and some child menus underneath them:


The pure YAML version of the build file for this looks like this:

http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/menu/FrameWithMenu.yaml

but the compressed version is WAY smaller less verbose:

http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/menu/FrameWithMenuCondensed.yaml

Basically, this allows you across the board to define an entire object and all of its properties in one line of "enhanced" YAML using the virtual constructor flow.

The latest build of Java SwingBuilder with support for this enhanced format is up on javabuilders.org.

P.S. Here's another form converted to the new format with before/after samples:

Before:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/binding/BindingFrame1.yaml?r=150
After:
http://code.google.com/p/javabuilders/source/browse/trunk/org.javabuilders.swing/samples/org/javabuilders/swing/samples/binding/BindingFrame1.yaml?r=157

Less code and less lines to type = good! :-)

3 comments:

Anonymous said...

Ultima Online Gold, UO Gold, crestingwait
buy uo gold
buy uo gold
buy uo gold
buy uo gold
buy uo gold
buy uo gold
buy uo gold
buy uo gold
buy uo gold
buy uo gold
lotro gold
wow gold
warhammer gold
buy aoc gold
buy aoc gold
buy aoc gold
buy aoc gold
buy aoc gold
buy aoc gold
buy aoc gold
Age of Conan Gold, AOC Gold

Anonymous said...

Sometimes in the Shadow of Legend game, after winning the enemies, they will understand to share the shadow of legend Gold as their trophy. A beautiful and rich sol gold environment coupled with an engrossing storyline in this Shadow of Legend game. A once beautiful and lush world and the first process you have to buy shadow of legend Gold, the game in fact is full of creatures and inhabitants. He constant warring left the fate of the inhabitants with cheap shadow of legend Gold of Agnes at the hands of the gods. Shadow of legend and the necessary or useful shadow of legend money is the answer for you.

wholesale jewelry said...

wholesale jewelryhandmade jewelryjewelry wholesalefashion jewelrycostume jewelry