If you have worked in Java for a healthy amount of time you have probably come across Format, specifically DateFormat, NumberFormat and MessageFormat. All of these are crazy awesome but I find that I need another type of formatter that isn't part of the standard Java offerings - PatternFormatter. I love how you can use SimpleDateFormat to customize the layout of a date but I come across several situations that I wish I could come up with my own formatting tokens to format anything - Phone Numbers, Addresses, ZIP codes or any other varying but standardized format. I've spent many a night trying to solve this problem but I think I finally have something that is workable and simple...
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PatternFormatter {
public static interface TokenEditor {
String replace(String token);
}
private static final String EMPTY_STRING = "";
private TokenEditor _editor;
private Pattern _pattern;
public PatternFormatter(Pattern pattern, TokenEditor editor) {
_pattern = pattern;
_editor = editor;
}
public PatternFormatter(String regex, TokenEditor editor) {
this(Pattern.compile(regex), editor);
}
/**
* Finds all matching pattern tokens and delegates the replacement to the
* {@link TokenEditor}. The pattern token is passed along to the editor so it
* can determine the appropriate replacement.
*
* @param mask
* to use against the pattern
* @return the formatted string
*/
public String format(String mask) {
Matcher matcher = _pattern.matcher(mask);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String replacement = _editor.replace(matcher.group());
matcher.appendReplacement(sb, replacement == null ? EMPTY_STRING : replacement);
}
matcher.appendTail(sb);
return sb.toString();
}
}
Then to compose the Pattern formatter in a class...
public class Phone implements TokenEditor {
private Integer _areaCode, _prefix, _lineNumber;
public String replace(String token){
if(isNotBlank(token)){
if(contains(token, "a")){
if(_areaCode != null) return leftPad(_areaCode.toString(), length(token), "0");
} else if(contains(token, "p")){
if(_prefix != null) return leftPad(_prefix.toString(), length(token), "0");
} else if(contains(token, "n")){
if(_lineNumber != null)) return leftPad(_lineNumber.toString(), length(token), "0");
}
return null;
}
}
private PatternFormatter _formatter = new PatternFormatter("[apn]+|\"[^\"]*\"|'[^']*'", this);
public String format(String mask){
_formatter.format(mask);
}
}
Finally to use...
new Phone(555, 222, 3333).format("(aaa) ppp-nnnn"); = "(555) 222-3333"
new Phone(555, 2, 33).format("(aaa) ppp-nnnn"); = "(555) 002-0033"
No comments:
Post a Comment