Intercept method calls in Groovy for automatic type conversion
Posted
by kerry
on Gooder Code
See other posts from Gooder Code
or by kerry
Published on Tue, 10 Aug 2010 11:28:00 +0000
Indexed on
2010/12/06
16:59 UTC
Read the original article
Hit count: 399
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!
© Gooder Code or respective owner