package org.msh.utils; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.intercept.BypassInterceptors; import org.jboss.seam.international.Messages; import org.msh.utils.date.DateUtils; import org.msh.utils.date.Period; import javax.faces.component.UIComponent; import javax.faces.component.UIParameter; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Map; @Name("periodConverter") @org.jboss.seam.annotations.faces.Converter(id="periodConverter") @BypassInterceptors public class PeriodConverter implements Converter{ private Period period; public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { return null; } public String getAsString(FacesContext facesContext, UIComponent comp, Object obj) { if (obj == null) return null; UIParameter p = findParam(comp, "type"); String typeName = (p == null? null: p.getValue().toString()); period = getPeriod(comp, obj); if ((typeName == null) || (typeName.equals("period"))) return getAsPeriod(); else if (typeName.equals("length")) return getAsLength(comp, obj); else if (typeName.equals("time-length")) return getAsTimeLength(comp, obj); else if (typeName.equals("elapsed-time")) return getAsElapsedTime(); else if(typeName.equals("month")) return getAsMonth(comp, obj); else return null; } /** * Convert the period to a format "initial date...end date (number of days)" * @param comp * @param obj * @return */ protected String getAsPeriod() { long days = period.getDays() + 1; Map messages = Messages.instance(); String dayTxt; if (days == 0) dayTxt = ""; else if (days == 1) dayTxt = " (" + days + " " + messages.get("global.day") + ")"; else dayTxt = " (" + days + " " + messages.get("global.days") + ")"; SimpleDateFormat dtf = new SimpleDateFormat(Messages.instance().get("locale.outputDatePattern")); String s = dtf.format(period.getIniDate()) + "..." + dtf.format(period.getEndDate()) + dayTxt; return s; } protected String getAsTimeLength(UIComponent comp, Object obj) { Calendar c = DateUtils.calcDifference(period.getIniDate(), period.getEndDate()); long len = c.getTimeInMillis(); String s = ""; Map messages = Messages.instance(); // is bigger than 24 hours ? if (len > 1000 * 60 * 60 * 24) { Date dt = period.getIniDate(); int years = DateUtils.yearsBetween(dt, period.getEndDate()); dt = DateUtils.incYears(dt, years); int months = DateUtils.monthsBetween(dt, period.getEndDate()); dt = DateUtils.incMonths(dt, months); int days = DateUtils.daysBetween(dt, period.getEndDate()); if (years > 0) { if (years == 1) s = years + " " + messages.get("global.year"); else s = years + " " + messages.get("global.years"); } if (months > 0) { if (!s.isEmpty()) s = s + ", "; if (months == 1) s = s + months + " " + messages.get("global.month"); else s = s + months + " " + messages.get("global.months"); } if (days > 0) { if (!s.isEmpty()) s = s + ", "; if (days == 1) s = s + days + " " + messages.get("global.day"); else s = s + days + " " + messages.get("global.days"); } } else { //Check if both dates used to calc the period has time, if not returns empty. Calendar c1 = Calendar.getInstance(); Calendar c2 = Calendar.getInstance(); c1.setTime(period.getIniDate()); c2.setTime(period.getEndDate()); if((c1.get(Calendar.HOUR_OF_DAY) == 0 && c1.get(Calendar.MINUTE) == 0 && c1.get(Calendar.SECOND) == 0 && c1.get(Calendar.MILLISECOND) == 0) || (c2.get(Calendar.HOUR_OF_DAY) == 0 && c2.get(Calendar.MINUTE) == 0 && c2.get(Calendar.SECOND) == 0 && c2.get(Calendar.MILLISECOND) == 0)){ return s; } int hours = (int)Math.floor((float)len / (1000F * 60F * 60F)); if (hours > 0) len %= (hours * 1000 * 60 * 60); int min = (int)Math.floor((float)len / (1000F * 60F)); if (min > 0) len %= (min * 1000 * 60); int sec = (int)Math.floor((float)len / 1000F); if (hours > 0) { if (hours > 1) s = hours + " " + messages.get("global.hour"); else s = hours + " " + messages.get("global.hours"); } if (min > 0) { if (!s.isEmpty()) s += " "; s += min + " " + messages.get("global.min"); } if ((hours == 0) && (sec > 0)) { if (!s.isEmpty()) s += " "; s += sec + " " + messages.get("global.sec"); } } return s; } /** * Converts to a string containing the length of two dates or in a number of days * @param comp - the component containing the value * @param obj - Can be a Date object indicating the beginning date or an Integer object indicating the number of days to be formated * @return */ protected String getAsLength(UIComponent comp, Object obj) { // make adjustment in the final date including 1 more day to count the exactly period of month or year Date dtIni = period.getIniDate(); Date dtEnd = period.getEndDate(); if ((dtIni == null) || (dtEnd == null)) return ""; dtEnd = DateUtils.incDays(dtEnd, 1); Map messages = Messages.instance(); int years = DateUtils.yearsBetween(dtIni, dtEnd); String s = ""; if (years > 0) { if (years == 1) s = years + " " + messages.get("global.year"); else s = years + " " + messages.get("global.years"); dtIni = DateUtils.incYears(dtIni, years); } int months = DateUtils.monthsBetween(dtIni, dtEnd); if (months > 0) { if (!s.isEmpty()) s = s + ", "; if (months == 1) s = s + months + " " + messages.get("global.month"); else s = s + months + " " + messages.get("global.months"); dtIni = DateUtils.incMonths(dtIni, months); } int days = DateUtils.daysBetween(dtIni, dtEnd); if (days > 0) { if (!s.isEmpty()) s = s + ", "; if (days == 1) s = s + days + " " + messages.get("global.day"); else s = s + days + " " + messages.get("global.days"); } return (s.isEmpty()? "-": s); } /** * Converts to a string containing the length of two dates or in a number of days * @param comp - the component containing the value * @param obj - Can be a Date object indicating the beginning date or an Integer object indicating the number of days to be formated * @return */ protected String getAsMonth(UIComponent comp, Object obj) { // make adjustment in the final date including 1 more day to count the exactly period of month or year Date dtIni = period.getIniDate(); Date dtEnd = period.getEndDate(); if ((dtIni == null) || (dtEnd == null)) return ""; dtEnd = DateUtils.incDays(dtEnd, 1); Map messages = Messages.instance(); String s = ""; /** * Commmenting code to fetch period in years. Instead the period is fetched in months */ // int years = DateUtils.yearsBetween(dtIni, dtEnd); // // // if (years > 0) { // if (years == 1) // s = years + " " + messages.get("global.year"); // else s = years + " " + messages.get("global.years"); // dtIni = DateUtils.incYears(dtIni, years); // } int months = DateUtils.monthsBetween(dtIni, dtEnd); if (months > 0) { if (!s.isEmpty()) s = s + ", "; if (months == 1) s = s + months + " " + messages.get("global.month"); else s = s + months + " " + messages.get("global.months"); dtIni = DateUtils.incMonths(dtIni, months); } int days = DateUtils.daysBetween(dtIni, dtEnd); if (days > 0) { if (!s.isEmpty()) s = s + ", "; if (days == 1) s = s + days + " " + messages.get("global.day"); else s = s + days + " " + messages.get("global.days"); } return (s.isEmpty()? "-": s); } public String getAsElapsedTime() { String s = getAsTimeLength(null, null); Map messages = Messages.instance(); /* Calendar c = DateUtils.calcDifference(period.getIniDate(), period.getEndDate()); long len = c.getTimeInMillis(); String s = ""; Map messages = Messages.instance(); // is bigger than 24 hours ? if (len > 1000 * 60 * 60 * 24) { Date dt = period.getIniDate(); int years = DateUtils.yearsBetween(dt, period.getEndDate()); dt = DateUtils.incYears(dt, years); int months = DateUtils.monthsBetween(dt, period.getEndDate()); dt = DateUtils.incMonths(dt, months); int days = DateUtils.daysBetween(dt, period.getEndDate()); if (years > 0) { if (years == 1) s = years + " " + messages.get("global.year"); else s = years + " " + messages.get("global.years"); } if (months > 0) { if (!s.isEmpty()) s = s + ", "; if (months == 1) s = s + months + " " + messages.get("global.month"); else s = s + months + " " + messages.get("global.months"); } if (days > 0) { if (!s.isEmpty()) s = s + ", "; if (days == 1) s = s + days + " " + messages.get("global.day"); else s = s + days + " " + messages.get("global.days"); } } else { int hours = Math.round((float)len / (1000F * 60F * 60F)); int min = Math.round((float)len / (1000F * 60F)); int sec = Math.round((float)len / 1000F); if (hours > 0) { if (hours > 1) s = hours + " " + messages.get("global.hour"); else s = hours + " " + messages.get("global.hours"); } if (min > 0) { if (min > 1) s += min + " " + messages.get("global.min"); else s += min + " " + messages.get("global.mins"); } if (sec > 0) { if (sec > 1) s += sec + " " + messages.get("global.sec"); else s += sec + " " + messages.get("global.secs"); } } */ if (!s.isEmpty()) s = MessageFormat.format(messages.get("global.timeago"), s); return s; } /** * Search for a {@link UIParameter} child of the comp parameter * @param comp Component that has the parameter as a child * @param pname Name of the {@link UIParameter} component * @return {@link UIParameter} instance */ public UIParameter findParam(UIComponent comp, String pname) { for (UIComponent c: comp.getChildren()) { if ((c instanceof UIParameter) && (((UIParameter)c).getName().equals(pname))) { return (UIParameter)c; } } return null; } /** * Return the period indicated in the component * @param comp * @param obj * @return */ protected Period getPeriod(UIComponent comp, Object obj) { if (obj == null) return null; Period p; if (obj instanceof Period) p = (Period)obj; else { Date dt = (Date)obj; p = new Period(); p.setIniDate(dt); UIParameter paramDtEnd = findParam(comp, "endDate"); if (paramDtEnd != null) p.setEndDate( (Date)paramDtEnd.getValue() ); if (p.getEndDate() == null) p.setEndDate( new Date() ); } return p; } }