Groovy Builders

Post by Scott Vlaminck

I’ve still been thinking about Builders so I dug into Groovy Builders and presented at the Groovy Users of Minnesota (GUM) meeting last night. Since I was inspired by Nat’s post, I used the same example domain that he used.

Builders encapsulate the logic of how an object is assembled. Groovy Builders do this using a tree based syntax. Starting with the end in mind – and after doing a little research into how Groovy Builders work (Chapter 8 of Groovy in Action is a great start) – as a basic first step, this is how I would like to describe an invoice:

def invoice = builder.invoice()
{
  recipient(name:'Sherlock Holmes')
  {
    address(street:'222b Baker Street', city:'London')
  }
  invoiceLines
  {
    invoiceLine(item:'Deerstalker Hat')
    {
      poundsShillingsPence(pounds:0, shillings:3, pence:10)
    }
    invoiceLine(item:'Tweed Cape')
    {
      poundsShillingsPence(pounds:0, shillings:4, pence:12)
    }
  }
}

Now for a quick intro into how Groovy Builders work. Creating a builder begins by extending the abstract class BuilderSupport and implementing a few createNode() methods and a setParent() method (with an option to implement nodeCompleted()). The following pseudocode illustrates how BuilderSupport uses these callback methods:

invoice = createNode('invoice')
//setParent() is not called on the root node

  recipient = createNode('recipient', [name:'Sherlock Holmes'])
  setParent(invoice, recipient)

    address = createNode('address', [street:'222b Baker', city:'London'])
    setParent(recipient, address)
    nodeCompleted(recipient, address)

  nodeCompleted(invoice, recipient)
  // etc ...
nodeCompleted(null, invoice)

I started down the path of creating an InvoiceBuilder as Nat had, but then I started thinking that I could do it in a more generic way that may fit what I needed to do. So rather than start in that direction, for the purposes of this example I decided to create a generic ObjectGraphBuilder that would build any object tree for me, as long as I followed some naming conventions along the way. Here’s the important bits of my builder:

class ObjectGraphBuilder extends BuilderSupport {
  def createNode(def name, Map attributes, def value) {
    if(attributes) {
      return Class.forName(capitalize(name)).newInstance(attributes)
    } else {
      return Class.forName(capitalize(name)).newInstance()
    }
  }
  def setParent(def parent, def child) {
    setObject(child, parent)
    setObject(parent, child)
  }
}

The capitalize() and setObject() methods are just helper methods I created that don’t really have any bearing on how the builder works. The first just uses WordUtils to capitalize the node name and the builder makes the assumption that it should instantiate a class by that name. The second uses reflection to fill in the association between the parent and child nodes as appropriate. The interested reader can find the code available here at the GUM Google Code repository. In addition to the builder and domain classes, there’s a test that executes the builder and asserts that the structure is set up as expected.

For building data objects for test purposes, this example doesn’t quite get to the level of simplicity that Nat’s example does. But next up, I’m hoping to work up an example using nested builders, which may do a better job for that purpose.

About Scott Vlaminck

believes software development is more about people than technology; believes in agile processes; software developer, engineer, designer, architect, or whatever they're calling us these days; enjoys discussing software design; working on a program to write other programs (but it hasn't written itself yet).
This entry was posted in Agile Processes and tagged , , . Bookmark the permalink.

Related Posts:

6 Responses to Groovy Builders

  1. Pingback: Enfranchised Mind » links for 2007-10-11

  2. ObjectGraphBuilder is a great idea, have you considered the possibility of donating it to the Groovy project? =)

  3. I have definitely thought about contributing the code to the Groovy project. The ObjectGraphBuilder I have is currently pretty naive, so I was planning to put more time into it first. But I guess I should probably just contribute it and worry about improving it later. That way it would be of more use to others sooner.

  4. Pingback: refactr Blog Archive » Refactr Contributions to Grails and Groovy

  5. Hi,

    I tried something similar a while back: http://www.behindthesite.com/blog/C663408438/E876434710/index.html

    I never got to use it for real and I’m not sure if the builder API has changed.

    Cheers,

    Mike

  6. ccda exam says:

    For the construction of data objects for testing purposes, this example does not quite reach the level of simplicity that makes the example of Nat. But next, I’m hoping to work up an example using nested constructors, you can do a better job for this purpose.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>