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 firstname or a title, but some of the 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 by a 40 line Groovy implementation “Salutation.groovy”, that shows a much simpler approach to the same problem using a Groovy closure to create the salutation string. Here is the code, mayit be useful for the rest of the world:
- class Salutation {
- private StringBuilder buf = new StringBuilder()
- private boolean touched, said
-
- return new Salutation(defaultSalutation: defaultSalutation).salute(builder)
- }
-
- with builder
- return 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 && said) {
- touched = true
- buf.append(text)
- said = false
- }
- }
- }
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)
- // Example 1
-
- add(person.gender=='male':'Mr.' ?'Mrs.')
- add(person.title)
- gap(' ')
- add(person.firstName)
- gap(' ')
- add(person.lastName)
- }) // results in => "Mr. Dr Peter Miller"
-
- // Example 2
-
- add(person.title)
- gap(' ')
- add(person.lastName)
- gap(', ')
- add(person.firstName)
- }) // results in => "Miller, Peter"
-
- // Example 3
-
- add(person.title)
- gap(' ')
- add(person.lastName)
- gap(', ')
- add(person.firstName)
- }, "customer") // results in => "Miller"
-
- // Example 4
-
- add(person.title)
- gap(' ')
- add(person.lastName)
- gap(', ')
- add(person.firstName)
- }, "customer") // results in => "customer"
A salute to Groovy! To write this post took more time than to implement the code.