November 19, 2013

Groovy Goodness: Choose Which Delegated Methods to Use

In Groovy we can use the @Delegate annotation for some time now to automatically include methods from a delegated class into our own class. When the method is invoked on our class, it will be delegated to the correct class. Since Groovy 2.2 we can use the includes and excludes annotation parameters to define which methods of the delegated class we want to use in our own class. If any required method from the delegated class, which can also be defined in an interface, is left out when we use includes and excludes, then we get a compilation error, telling us to implement the required method from the delegated class or interface.

In the following sample we define a SimpleEvent class with a start and end property we delegate to the Date class. For the start property we don't want the after() method to be delegated, because we want to delegate it to the Date object of the end property. And for the end property we want to delegate the before() delegated method of the Date object of the start property.

class SimpleEvent {
    @Delegate(excludes=['after']) Date start
    @Delegate(excludes=['before']) Date end
    String description

def event = new SimpleEvent(description: 'Groovy seminar',
                            start: nextWeek, 
                            end: nextWeek + 3)

// Delegate to Date start property.
assert event.before(nextWeek + 1)
assert !event.before(nextWeek - 1)
assert !event.before(today)

// Delegate to Date end property.
assert event.after(today)        
assert event.after(nextWeek + 1)     
assert !event.after(nextWeek + 4)        

// Helper get methods:
def getToday() {
    new Date().clearTime()

def getNextWeek() {
    today + 7

Code written with Groovy 2.2.