Ok. Since the train wrecks in the name inverter class seemed weird and avoidable,
the refactoring bug got into me and I decided to try to clean up the code.
What I found was the there is no need for the NameInverter class.
All that is required is a PersonName class that knows about names, honorifics and postnominals
and a NameFormatter interface and its implementation, that produces a string based on a
PersonName class.
Here is the code:
-----------------------------------------------------------
PersonName class
-----------------------------------------------------------
import java.util.ArrayList;
import java.util.List;
public class PersonName {
private List<String> nameElements = new ArrayList<String>();
private List<String> honorifics = new ArrayList<String>();
private List<String> postnominals = new ArrayList<String>();
private String honorificRegex = "MR\\.|MRS\\.|MS\\.|HRM|SIR|LORD|MR|MRS|MS|PROF|PROF\\.";
private String postnominalRegex = "PHD\\.|BS\\.|PHD|BS|MD|CEO|CFO|CIO|I|II|III|ESQ|ESQ\\.|SR\\.|SR|JR\\.|JR";
public PersonName(String name){
if(name==null) return;
String[] elements = splitInputName(name);
for(int i=0;i<elements.length;i++){
String nameElement = elements[i].trim();
classify(nameElement);
}
}
private String[] splitInputName(String name){
return name.trim().split("\\s+");
}
private void classify(String nameElement){
if(nameElement.toUpperCase().matches(honorificRegex))
honorifics.add(nameElement);
else if(nameElement.toUpperCase().matches(postnominalRegex))
postnominals.add(nameElement);
else
nameElements.add(nameElement);
}
public List<String> getNameElements(){
return nameElements;
}
public List<String> getHonorifics(){
return honorifics;
}
public List<String> getPostnominals(){
return postnominals;
}
}
-----------------------------------------------------------
NameFormatter interface implementation
-----------------------------------------------------------
import java.util.List;
public class LastFirstPostnominalsFormatter implements NameFormatter {
public String formatName(PersonName name){
String formattedName="";
if(name==null) return formattedName;
formattedName += getLastNameFrom(name);
String firstName = getCombinedFirstNameFrom(name);
String postnominals = getPostnominalsFrom(name);
if(!firstName.equals("")) formattedName+=", " + firstName;
if(!postnominals.equals("")) formattedName += " " + postnominals;
return formattedName;
}
private String getCombinedFirstNameFrom(PersonName name){
List<String> nameElements = name.getNameElements();
if(nameElements.size()==0) return "";
return combineListIntoSpacedString(nameElements.subList(0, nameElements.size()-1));
}
private String getLastNameFrom(PersonName name){
List<String> nameElements = name.getNameElements();
if(nameElements.size()==0) return "";
return nameElements.get(nameElements.size()-1);
}
private String getPostnominalsFrom(PersonName name){
return combineListIntoSpacedString(name.getPostnominals());
}
private String combineListIntoSpacedString(List<String> list){
String result = "";
for(int i=0;i<list.size();i++){
result += list.get(i);
if(i<list.size()-1)
result+=" ";
}
return result;
}
}
These two classes pass all the original tests, but can also handle middle names and a large variety of
honorifics and postnominals.
The regexes are kind of ugly, but then again, they always are ;). Also the multiple if - else if statements
in the classify method are bugging me.
So, there you go.
Any feedback would be much appreciated.