Groovy Overload (of Operators)

I was recently working on a pretty long class which mapped a web-service response to a set of 'activity codes' in our Java application. The class ends up mapping some 60+ different codes based on various scenarios, and appends some extra data for some. The code was original written in Java and pretty well organized (okay I wrote it, so I may be bias), but it was very wordy, there were a lot of repeated words/verbs in the class.

So, I set about re-writing this class in Groovy, not just for the wordiness, there were some additional complexities to the rules that I needed to apply, but I wanted to make this monstrosity easier to understand. I made use of Groovy's capability to use Strings in switch statements (coincidentally, we were given the okay to use Java 7 the following week...), which helped (previously I had been converting the Strings into enum), and I made use of Groovy's implicit calls to setters and it's concise map notation. All of which made a big difference. I also used static imports for my enums so the names were shorter. So the code looked like this in the end.

details.activityCode = PAYMENT_TRANSFER_IN
details.activityProperties[REVERSAL_REAPPLIED_TO] = pay.transferAcct
details.activityProperties[ACCOUNT_NUMBER] = pay.transferAcct

But I wanted to go one step further, every single one of our activities had an activityCode, that's the primary data we're mapping, and the activity properties was only the only map in the object. So saying .activityCode and .activityProperties was redundant. What I really wanted was something more concise like this:

details << PAYMENT_TRANSFER_IN
details[REVERSAL_REAPPLIED_TO] = pay.transferAcct
details[ACCOUNT_NUMBER] = pay.transferAcct

And thanks to Groovy's ability to add methods which override operators, that was an easy task. These are the relevant parts of my POJO to support this notation. 

private String activityCode;
private Map<ActivityType, String> activityProperties = new HashMap<>();

//Overrides the '<<' operator in groovy code to set the account activity code.
public void leftShift(ActivityCode value) {
  this.setActivityCode(value);
}

// Used with groovy map notation to get activityProperties values.
public String getAt(Object key) {
  return this.sapProperties.get(key);
}

// Used with groovy map notation to set activityProperties values.
public String putAt(AccountActivityTypeDescriptor key, Object value) {
  if (value != null) {
    return this.sapProperties.put(key, String.valueOf(value));
  }
  return null;
}

Note: I could add leftShift methods for other object types too, like the amount, which is also often set on these objects, but I still want the code to be readable, that's the whole reason I was exploring this change, so since the activity code is the one that gets used repeatedly, that's the only value where I implemented leftShift.

The finally effect is much less code to read through, which makes understanding this massive class considerably easier.

Post a Comment