package er.extensions.formatters; import java.text.FieldPosition; import java.text.Format; import java.text.ParsePosition; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalQuery; import java.util.Objects; /** * Base formatter class for wrapping a {@link DateTimeFormatter} into something * that extends {@link Format} so you can safely use it with components that * would expect old formatter types. * * @author jw */ public abstract class ERXDateTimeFormatter extends Format { private static final long serialVersionUID = 1L; private final DateTimeFormatter formatter; private final TemporalQuery<?> query; private final String pattern; /** * Basic constructor. * * @param formatter * the formatter to encapsulate * @param query * the method to extract correct date object from parsed results */ public ERXDateTimeFormatter(DateTimeFormatter formatter, TemporalQuery<?> query) { this(formatter, query, null); } /** * Constructor that takes an additional string pattern. DateTimeFormatter * objects unfortunately don't retain their pattern so you can't extract it * from the object anymore. Some component like AjaxDatePicker though need * that information so you can provide it with this constructor. * * @param formatter * the formatter to encapsulate * @param query * the method to extract correct date object from parsed results * @param pattern * the pattern used by the formatter */ public ERXDateTimeFormatter(DateTimeFormatter formatter, TemporalQuery<?> query, String pattern) { this.formatter = Objects.requireNonNull(formatter, "formatter must not be null"); this.query = Objects.requireNonNull(query, "query must not be null"); this.pattern = pattern; } @Override public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { if (obj instanceof TemporalAccessor) { formatter.formatTo((TemporalAccessor) obj, toAppendTo); } return toAppendTo; } @Override public Object parseObject(String source, ParsePosition pos) { Object date = formatter.parse(source, query); pos.setIndex(source.length()); return date; } /** * The formatter to be used. * * @return the formatter */ public DateTimeFormatter formatter() { return formatter; } /** * The method reference that will create the correct object type from parsed * result. * * @return query for the parsed temporal object */ protected TemporalQuery<?> query() { return query; } /** * The pattern used for the formatter. This information has to be given * during construction of this object as DateTimeFormatter objects don't * contain their original pattern as string. * * @return the pattern or null if none was provided */ public String pattern() { return pattern; } @Override public String toString() { StringBuilder sb = new StringBuilder().append('<').append(getClass().getName()) .append(" formatter=").append(formatter) .append(" pattern=").append(pattern).append('>'); return sb.toString(); } }