Intercept method calls in Groovy for automatic type conversion
- by kerry
One of the cooler things you can do with groovy is automatic type conversion. If you want to convert an object to another type, many times all you have to do is invoke the ‘as’ keyword:
def letters = 'abcdefghijklmnopqrstuvwxyz' as List
But, what if you are wanting to do something a little fancier, like converting a String to a Date?
def christmas = '12-25-2010' as Date
ERROR org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '12-25-2010' with class java.lang.String' to class 'java.util.Date'
No bueno!
I want to be able to do custom type conversions so that my application can do a simple String to Date conversion. Enter the metaMethod. You can intercept method calls in Groovy using the following method:
def intercept(name, params, closure) {
def original = from.metaClass.getMetaMethod(name, params)
from.metaClass[name] = { Class clazz ->
closure()
original.doMethodInvoke(delegate, clazz)
}
}
Using this method, and a little syntactic sugar, we create the following ‘Convert’ class:
// Convert.from( String ).to( Date ).using { }
class Convert {
private from
private to
private Convert(clazz) { from = clazz }
static def from(clazz) {
new Convert(clazz)
}
def to(clazz) {
to = clazz
return this
}
def using(closure) {
def originalAsType = from.metaClass.getMetaMethod('asType', [] as Class[])
from.metaClass.asType = { Class clazz ->
if( clazz == to ) {
closure.setProperty('value', delegate)
closure(delegate)
} else {
originalAsType.doMethodInvoke(delegate, clazz)
}
}
}
}
Now, we can make the following statement to add the automatic date conversion:
Convert.from( String ).to( Date ).using { new java.text.SimpleDateFormat('MM-dd-yyyy').parse(value) }
def christmas = '12-25-2010' as Date
Groovy baby!