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 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:

  1. class Salutation {
  2. private StringBuilder buf = new StringBuilder()
  3. private boolean touched, said
  4. String defaultSalutation = ''
  5.  
  6. static format(Closure builder, String defaultSalutation = '') {
  7. return new Salutation(defaultSalutation: defaultSalutation).salute(builder)
  8. }
  9.  
  10. String salute(Closure builder) {
  11. with builder
  12. return toString()
  13. }
  14.  
  15. String toString() {
  16. if (touched) {
  17. return buf.toString()
  18. } else {
  19. return defaultSalutation
  20. }
  21. }
  22.  
  23. void add(def text) {
  24. if (text) {
  25. touched = true
  26. buf.append(text)
  27. said = true
  28. } else {
  29. said = false
  30. }
  31. }
  32.  
  33. void gap(def text) {
  34. if (text && said) {
  35. touched = true
  36. buf.append(text)
  37. said = false
  38. }
  39. }
  40. }

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)

  1. // Example 1
  2. def person = [firstName: 'Peter', lastName: 'Miller', title: 'Dr', gender: 'male']
  3.  
  4. def salutation = Salutation.format({
  5. add(person.gender=='male':'Mr.' ?'Mrs.')
  6. add(person.title)
  7. gap(' ')
  8. add(person.firstName)
  9. gap(' ')
  10. add(person.lastName)
  11. }) // results in => "Mr. Dr Peter Miller"
  12.  
  13. // Example 2
  14. def person = [firstName: 'Peter', lastName: 'Miller']
  15.  
  16. def salutation = Salutation.format({
  17. add(person.title)
  18. gap(' ')
  19. add(person.lastName)
  20. gap(', ')
  21. add(person.firstName)
  22. }) // results in => "Miller, Peter"
  23.  
  24. // Example 3
  25. def person = [lastName: 'Miller']
  26.  
  27. def salutation = Salutation.format({
  28. add(person.title)
  29. gap(' ')
  30. add(person.lastName)
  31. gap(', ')
  32. add(person.firstName)
  33. }, "customer") // results in => "Miller"
  34.  
  35. // Example 4
  36. def person = [:]
  37.  
  38. def salutation = Salutation.format({
  39. add(person.title)
  40. gap(' ')
  41. add(person.lastName)
  42. gap(', ')
  43. add(person.firstName)
  44. }, "customer") // results in => "customer"

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

Kommentare sind deaktiviert