organic thoughts

seemingly random and unorgainzed bits of information

2.25.2008

Creating a Simple Builder with Groovy's methodMissing()

Creating a Simple Builder with Groovy's methodMissing()

One of the main theme here at Groovy/Grails Experience is Meta Programming: the ability to use Groovy to dynamically modify the behavior of the language at runtime. During one of Graeme Rocher's session, he did a live demo on how to build a simple Xml builder and Vankat Subramaniam demo'ed the creation of a simple DSL using Groovy. These sessions showed the simplicity and power of Meta programming in Groovy. So, rather than go on and praise the merits of Groovy and make this an all fluff write up (and get crap for it from my buddy James Williams ), I will show a concrete example below.

A Simple Xml Builder in Groovy
This simple xml builder is able to handle most xml tag constructs including:

Sorry, there is no namespace support of the form <namespace:tag/>

So, here is a sample usage of the SimpleXmlBuilder class to build XML nodes:

The code snippet above will generate this HTML code:

<html xmlns="htt://namespace" ><header><title>Hello</title></header><body><p>Hello World Sample</p><span id="greet" style="font-family:sans-serif" >Hello World!!</span></body></html>


The Code
Disclaimer: this was put together in less an hour while sitting in a session at the G2 Experience. I am sure it can be done in a more elegant way. The code simply evaluates each of the syntatic possiblities (discussed above) and take appropritae action. So, with that out of the way, here is the code for simple xml builder:

Click to download the Groovy source code.

MOP - methodMissing()
If you are new to Groovy then you may not understand what's going on. Groovy's meta object protocol (MOP) lets developers expand the syntactical constraints of the core language at runtime. This capability makes Groovy the perfect platform to create Domain Specific Language (DSL) where you develop small language with a concise syntax to address a given domain (software dev, business, etc). The methodMissing() method is one of the hooks exposed by Groovy's MOP mechanism that intercepts all calls to undefined methods on a given object. By overriding methodMissing(), you can implement behaviors of methods that are not statically defined on the class.

When Groovy's MOP intercepts an method call, it invokes methodMissing(String methodName, args) with two parameters: the name of the missing method that was invoked and an array representing the method's parameters. So, for instance, when Groovy intercepts xml.title("Hello"), the first parameter of methodMissing() has a value of "title" and args.length = 1 where arg[0] = "Hello".

When the syntax is as follows, xml.header {...}, methodMissing's method name has a value of "header". Here, however, args[0] is a closure. A closure is an executable (callable) code block that can be treated as a variable. As such, we must tell Groovy that we want to execute that code block. However, before we blindly call the closure, we reassign the closure's target to be the SimpleXmlBuilder class (args[0].delegate = this line 11 and 49). Therefore, the next method dispatch request on the closure will be handled by the SimpleXmlBuilder.

Finally, when the syntax of our builder takes the form of xml.html(xmlns:"http;//somenamespace"){ ... }, Groovy's MOP invokes methodMissing where the method name is "html" as expected. In this case, however, argument array has two memebers: the first one is a map and the second member is another closure. Knowing this, we can handle tags with both attributes and function as a container tag as shown above (starting with line 37).

Conclusion

This sample code above demonstrates how Groovy's MOP mechanism can let developers change and extend the language's syntactical behavior to build functional DSL that fit specific needs. Here, in about 30 lines of code, we created a simple XML builder which is able to output well-formed xml document. This is a simple example and shows just a small glimpse of the capabilities of Groovy's meta programming. I hope this inspires you to continue to explore Groovy and come up with your own use for MOP.

References
0. Download Groovy source file - http://vmatters.googlepages.com/SimpleBuilderDemo.groovy
1. Dynamic Groovy - http://groovy.codehaus.org/Dynamic+Groovy
2. Using methodMissing and propertyMissing - http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing
3. Meta Programming with Groovy Part 1 - http://groovy.dzone.com/articles/metaprogramming-groovy-i
4. Meta Programming with Groovy Part 2 - http://groovy.dzone.com/articles/metaprogramming-groovy-ii-expa
5. Google Doc version of this write up - http://docs.google.com/Doc?id=df3qdpw5_53chtkh89r





Labels: , ,






<< Home

This page is powered by Blogger. Isn't yours?