Groovy salutes you!

Some time ago in one of my previous projects, we had to generate customer salutations in emails and SMS texts in various ways, like these example show:

"Dear Mr. John Miller", "Dear Mrs. Dr. Miller", "Miller, John"

The task was nasty because sometimes the user object had a first name or a title, but some fields were optional so that it could result in:

"Dear Mr. null Miller" (when firstname was null) or
"Miller, " (when firstname as "")

It showed, that a utility class would be useful, that helps to generate the salutation strings and fill the gaps between “firstname”, “lastname”, “title” etc. only when the parts are not empty. A java implementation named “SalutationUtil” was implemented, consisting of a 230 line class “SalutationParser”, that parsed an expression string and a 140 line class “SalutationUtil” to present an API. We used a ResourceBundle to fill the “Dear” and “Mr.” parts according to the language to be used and the gender of the person to be addressed.

Now, in our current project, we had the same problem and I was thinking to reuse the java implementation. No problem, because although we are using Grails/Groovy nowadays, the “SalutationUtil” would still be compatible. After some minutes of looking at the java code, I dropped it and replaced the whole “SalutationUtil” and the parser-class with a 40 line Groovy implementation “Salutation.groovy”, which shows a much simpler approach to the same problem using a Groovy closure to create the salutation string. Here is the code, may it be useful for the rest of the world:

[codesyntax lang="java"]
<pre>class Salutation {
  private StringBuilder buf = new StringBuilder()
  private boolean touched, said
  String defaultSalutation = ''
 
  static format(Closure builder, String defaultSalutation = '') {
    return new Salutation(defaultSalutation: defaultSalutation).salute(builder)
  }
  
  String salute(Closure builder) {
    with builder
    return toString()
  }
 
  String toString() {
    if (touched) {
      return buf.toString()
    } else {
     return defaultSalutation
    }
  }
 
  void add(def text) {
    if (text) {
      touched = true
      buf.append(text)
      said = true
    } else {
      said = false
    }
  }
 
  void gap(def text) {
    if (text &amp;&amp; said) {
      touched = true
      buf.append(text)
      said = false
    }
  }
}</pre>
[/codesyntax]

It helps to separate the optional properties (firstname, lastname, title, …) with gaps to generate salutation strings. Here is an example how you can use the class (the ‘person’ Map is a placeholder for your User-Domain object)

[codesyntax lang="groovy"]
<pre>// Example 1
def person = [firstName: 'Peter', lastName: 'Miller', title: 'Dr', gender: 'male']
 
def salutation = Salutation.format({
 add(person.gender=='male':'Mr.' ?'Mrs.')
 add(person.title)
 gap(' ')
 add(person.firstName)
 gap(' ')
 add(person.lastName)
 }) // results in =&gt; "Mr. Dr Peter Miller"
 
// Example 2
def person = [firstName: 'Peter', lastName: 'Miller']
 
def salutation = Salutation.format({
 add(person.title)
 gap(' ')
 add(person.lastName)
 gap(', ')
 add(person.firstName)
 }) // results in =&gt; "Miller, Peter"
 
// Example 3
def person = [lastName: 'Miller']
 
def salutation = Salutation.format({
 add(person.title)
 gap(' ')
 add(person.lastName)
 gap(', ')
 add(person.firstName)
 }, "customer") // results in =&gt; "Miller"
 
// Example 4
def person = [:]
 
def salutation = Salutation.format({
 add(person.title)
 gap(' ')
 add(person.lastName)
 gap(', ')
 add(person.firstName)
 }, "customer") // results in =&gt; "customer"</pre>
[/codesyntax]

A salute to Groovy! To write this post took more time than to implement the code.

Scroll to Top