package pt.ist.renderers.extensions; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import org.joda.time.DateTimeFieldType; import org.joda.time.Partial; import org.joda.time.base.AbstractPartial; import pt.ist.renderers.DateInputRenderer; import pt.ist.renderers.components.HtmlComponent; import pt.ist.renderers.components.converters.ConversionException; import pt.ist.renderers.components.converters.Converter; import pt.ist.renderers.converters.DateConverter; import pt.ist.renderers.converters.MultipleFormatDateConverter; /** * By default the value of format is used to show to the user * how to write the date. The formatText property allows you to override that default. * This means that the value of the property will be shown instead. */ public class MultipleFormatTimeInputRenderer extends DateInputRenderer { private boolean minute; private boolean hour; private String inputFormat; public MultipleFormatTimeInputRenderer() { super(); minute = hour = false; } public boolean isHour() { return hour; } public void setHour(boolean hour) { this.hour = hour; } public boolean isMinute() { return minute; } public void setMinute(boolean minute) { this.minute = minute; } @Override public String getFormat() { // "HH:mm"; if (isFormatSet()) { return super.getFormat(); } StringBuilder format = new StringBuilder(); if (isHour()) { format.append((format.length() > 0 ? " " : "") + "HH"); } if (isMinute()) { format.append((format.length() > 0 ? ":" : "") + "mm"); } return format.toString(); } public String getInputFormat() { return this.inputFormat == null ? DateConverter.DEFAULT_FORMAT : inputFormat; } public void setInputFormat(String inputFormat) { this.inputFormat = inputFormat; } @Override protected HtmlComponent createTextField(Object object, Class type) { Date date = convertPartialToDate((AbstractPartial) object); return super.createTextField(date, type); } private Date convertPartialToDate(AbstractPartial partial) { if (partial == null) { return null; } Calendar calendar = Calendar.getInstance(); calendar.clear(); if (isHour()) { calendar.set(Calendar.HOUR_OF_DAY, partial.get(DateTimeFieldType.hourOfDay())); } if (isMinute()) { calendar.set(Calendar.MINUTE, partial.get(DateTimeFieldType.minuteOfHour())); } return calendar.getTime(); } @Override protected Converter getDateConverter(SimpleDateFormat dateFormat) { if (getInputFormat() != null) { dateFormat.applyPattern(getInputFormat()); } return new PartialConverter(new MultipleFormatDateConverter(dateFormat)); } public class PartialConverter extends Converter { private Converter dateConverter; public PartialConverter(Converter dateConverter) { this.dateConverter = dateConverter; } @Override public Object convert(Class type, Object value) { Date date = (Date) this.dateConverter.convert(type, value); if (date == null) { return null; } Calendar calendar = Calendar.getInstance(); calendar.setTime(date); try { return convertCalendarToPartial(type, calendar); } catch (Exception e) { throw new ConversionException("fenix.renderers.converter.timeOfDay", e, true, value); } } private Object convertCalendarToPartial(Class type, Calendar calendar) throws Exception { if (type.equals(Partial.class)) { Partial partial = new Partial(); if (isHour()) { partial = partial.with(DateTimeFieldType.hourOfDay(), calendar .get(Calendar.HOUR_OF_DAY)); } if (isMinute()) { partial = partial.with(DateTimeFieldType.minuteOfHour(), calendar .get(Calendar.MINUTE)); } return partial; } else { // ASSUMPTION // assume that we want a subtype of BasePartial and that the // subtype implements the factory // method fromCalendarField(Calendar calendar) Method method = type.getMethod("fromCalendarFields", new Class[] { Calendar.class }); return method.invoke(null, new Object[] { calendar }); } } } }