/** * TNTConcept Easy Enterprise Management by Autentia Real Bussiness Solution S.L. * Copyright (C) 2007 Autentia Real Bussiness Solution S.L. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.autentia.jsf.component.ocupation; import java.io.IOException; import java.lang.reflect.Array; import java.text.DateFormat; import java.text.DateFormatSymbols; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.Locale; import java.util.Map; import javax.faces.application.FacesMessage; import javax.faces.component.EditableValueHolder; import javax.faces.component.UIComponent; import javax.faces.component.UIInput; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; import javax.naming.NamingException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr; import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils; import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML; import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils; import org.apache.myfaces.shared_tomahawk.util.MessageUtils; /** * Calendar renderer. Render a Calendar in one row. Without popup mode. * * @extends org.apache.myfaces.custom.calendar.HtmlCalendarRenderer */ public class HtmlOcupationCalendarRenderer extends org.apache.myfaces.custom.calendar.HtmlCalendarRenderer { private static final Log log = LogFactory.getLog(HtmlOcupationCalendarRenderer.class); @Override public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException { log.debug("encodeEnd - component=\"" + component + "\"."); RendererUtils.checkParamValidity(facesContext, component, HtmlOcupationCalendar.class); HtmlOcupationCalendar inputCalendar = (HtmlOcupationCalendar) component; Locale currentLocale = facesContext.getViewRoot().getLocale(); Date value = null; Calendar timeKeeper = Calendar.getInstance(currentLocale); timeKeeper.setTime(new Date()); try { value = new CalendarDateTimeConverter().getAsDate(facesContext, inputCalendar); timeKeeper.setTime(value); } catch (IllegalArgumentException i) { log.warn("encodeEnd - IllegalArgumentException", i); } if (log.isDebugEnabled()) { log.debug("encodeEnd - timeKeeper=\"" + timeKeeper.getTime() + "\"."); } DateFormatSymbols symbols = new DateFormatSymbols(currentLocale); String[] weekdays = mapShortWeekdays(symbols); int lastDayInMonth = timeKeeper.getActualMaximum(Calendar.DAY_OF_MONTH); int currentDay = timeKeeper.get(Calendar.DAY_OF_MONTH); if (currentDay > lastDayInMonth) currentDay = lastDayInMonth; timeKeeper.set(Calendar.DAY_OF_MONTH, 1); int weekDayOfFirstDayOfMonth = mapCalendarDayToCommonDay(timeKeeper .get(Calendar.DAY_OF_WEEK)); int weekStartsAtDayIndex = mapCalendarDayToCommonDay(timeKeeper.getFirstDayOfWeek()); ResponseWriter writer = facesContext.getResponseWriter(); HtmlRendererUtils.writePrettyLineSeparator(facesContext); HtmlRendererUtils.writePrettyLineSeparator(facesContext); // render table writer.startElement(HTML.TABLE_ELEM, component); HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.UNIVERSAL_ATTRIBUTES); HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.EVENT_HANDLER_ATTRIBUTES); writer.flush(); HtmlRendererUtils.writePrettyLineSeparator(facesContext); // render days writeDays(facesContext, writer, inputCalendar, timeKeeper, currentDay, weekStartsAtDayIndex, weekDayOfFirstDayOfMonth, lastDayInMonth, weekdays); writer.endElement(HTML.TABLE_ELEM); } private void writeDays(FacesContext facesContext, ResponseWriter writer, HtmlOcupationCalendar inputComponent, Calendar timeKeeper, int currentDay, int weekStartsAtDayIndex, int weekDayOfFirstDayOfMonth, int lastDayInMonth, String[] weekdays) throws IOException { if (log.isDebugEnabled()) { log.debug("writeDays - currentDay=\"" + currentDay + "\", weekDayOfFirstDayOfMonth=\"" + weekDayOfFirstDayOfMonth + "\", lastDayInMonth=\"" + lastDayInMonth + "\", weekdays=\"" + Arrays.toString(weekdays) + "\"."); } OcupationModel ocupation = inputComponent.getOcupation(); Calendar cal; int space = (weekStartsAtDayIndex < weekDayOfFirstDayOfMonth) ? (weekDayOfFirstDayOfMonth - weekStartsAtDayIndex) : (weekdays.length - weekStartsAtDayIndex + weekDayOfFirstDayOfMonth); if (space == weekdays.length) space = 0; int extraDays = 0; try { extraDays = Integer.valueOf(inputComponent.getExtraDays()).intValue(); } catch (NumberFormatException e) { // nothing to do } for (int i = 0-extraDays; i < lastDayInMonth+extraDays; i++) { cal = copyCalendar(facesContext, timeKeeper); cal.set(Calendar.DAY_OF_MONTH, i + 1); int dayofweek = cal.get(Calendar.DAY_OF_WEEK); String cellStyle = inputComponent.getDayCellClass(); StringBuilder description = new StringBuilder(); // checking for vacations days Collection<OcupationEntry> entries = ocupation.getOcupationEntries(cal.getTime()); if (i < 0 || i >= lastDayInMonth) { cellStyle = inputComponent.getExtraDaysCellClass(); } if (entries != null && entries.size() > 0) { int performedHours = 0; int aEntryIsVacations = 0; for (OcupationEntry entry : entries) { performedHours += entry.getDuration(); if (entry.isVacances()) { aEntryIsVacations = 1; } else if(entry.isHoliday()) { aEntryIsVacations = 2; } description.append("[" + entry.getDescription() + "]"); } if (aEntryIsVacations==1) { cellStyle = inputComponent.getVacancesCellClass(); } else if (aEntryIsVacations==2) { cellStyle = inputComponent.getWeekEndCellClass(); } else { if (performedHours >= Integer.valueOf(inputComponent.getWorkingDayHours()).intValue()) { cellStyle = inputComponent.getFullWorkCellClass(); } else { cellStyle = inputComponent.getPartialWorkCellClass(); } } } else { description = null; } // week-end days if (dayofweek == 1 || dayofweek == 7) { description = new StringBuilder("Fin de semana"); cellStyle = inputComponent.getWeekEndCellClass(); } writeCell(facesContext, writer, inputComponent, String.valueOf(cal.get(Calendar.DAY_OF_MONTH)), null, cellStyle, description == null ? null : description.toString()); } } private void writeCell(FacesContext facesContext, ResponseWriter writer, UIInput component, String content, Date valueForLink, String styleClass, String description) throws IOException { writer.startElement(HTML.TD_ELEM, component); if (styleClass != null) writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null); if (description != null) { writer.writeAttribute(HTML.TITLE_ATTR, description, null); } writer.writeText(content, JSFAttr.VALUE_ATTR); writer.endElement(HTML.TD_ELEM); } private static String[] mapShortWeekdays(DateFormatSymbols symbols) { String[] weekdays = new String[7]; String[] localeWeekdays = symbols.getShortWeekdays(); weekdays[0] = localeWeekdays[Calendar.MONDAY]; weekdays[1] = localeWeekdays[Calendar.TUESDAY]; weekdays[2] = localeWeekdays[Calendar.WEDNESDAY]; weekdays[3] = localeWeekdays[Calendar.THURSDAY]; weekdays[4] = localeWeekdays[Calendar.FRIDAY]; weekdays[5] = localeWeekdays[Calendar.SATURDAY]; weekdays[6] = localeWeekdays[Calendar.SUNDAY]; return weekdays; } private int mapCalendarDayToCommonDay(int day) { switch (day) { case Calendar.TUESDAY: return 1; case Calendar.WEDNESDAY: return 2; case Calendar.THURSDAY: return 3; case Calendar.FRIDAY: return 4; case Calendar.SATURDAY: return 5; case Calendar.SUNDAY: return 6; default: return 0; } } private Calendar copyCalendar(FacesContext facesContext, Calendar timeKeeper) { Calendar cal = Calendar.getInstance(facesContext.getViewRoot().getLocale()); cal.setTime(timeKeeper.getTime()); return cal; } public void decode(FacesContext facesContext, UIComponent component) { RendererUtils.checkParamValidity(facesContext, component, HtmlOcupationCalendar.class); String helperString = ""; if (component instanceof EditableValueHolder) { Map<String, String> paramMap = facesContext.getExternalContext() .getRequestParameterMap(); String clientId = component.getClientId(facesContext); if (HtmlRendererUtils.isDisabledOrReadOnly(component)) return; if (paramMap.containsKey(clientId)) { String value = (String) paramMap.get(clientId); if (!value.equalsIgnoreCase(helperString)) { ((EditableValueHolder) component).setSubmittedValue(value); } else { ((EditableValueHolder) component).setSubmittedValue(""); } } else { log.warn("Warning! Component : " + RendererUtils.getPathToComponent(component)); } } } public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object submittedValue) throws ConverterException { RendererUtils.checkParamValidity(facesContext, uiComponent, HtmlOcupationCalendar.class); UIInput uiInput = (UIInput) uiComponent; Converter converter = uiInput.getConverter(); if (converter == null) converter = new CalendarDateTimeConverter(); if (submittedValue != null && !(submittedValue instanceof String)) { throw new IllegalArgumentException("Submitted value of type String expected"); } return converter.getAsObject(facesContext, uiComponent, (String) submittedValue); } public interface DateConverter extends Converter { public Date getAsDate(FacesContext facesContext, UIComponent uiComponent); } private static String getHelperString(UIComponent uiComponent) { return ""; } public static class CalendarDateTimeConverter implements DateConverter { private static final String CONVERSION_MESSAGE_ID = "org.apache.myfaces.calendar.CONVERSION"; public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) { if (s == null || s.trim().length() == 0 || s.equals(getHelperString(uiComponent))) return null; DateFormat dateFormat = createStandardDateFormat(facesContext); dateFormat.setLenient(false); try { return dateFormat.parse(s); } catch (ParseException e) { FacesMessage msg = MessageUtils.getMessage(CONVERSION_MESSAGE_ID, new Object[] { uiComponent.getId(), s }); throw new ConverterException(msg, e); } } public Date getAsDate(FacesContext facesContext, UIComponent uiComponent) { return RendererUtils.getDateValue(uiComponent); } public static String createJSPopupFormat(FacesContext facesContext, String popupDateFormat) { if (popupDateFormat == null) { SimpleDateFormat defaultDateFormat = createStandardDateFormat(facesContext); popupDateFormat = defaultDateFormat.toPattern(); } return popupDateFormat; } public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) { Date date = (Date) o; if (date == null) return getHelperString(uiComponent); DateFormat dateFormat = createStandardDateFormat(facesContext); dateFormat.setLenient(false); return dateFormat.format(date); } private static SimpleDateFormat createStandardDateFormat(FacesContext facesContext) { DateFormat dateFormat; dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, facesContext.getViewRoot() .getLocale()); if (dateFormat instanceof SimpleDateFormat) return (SimpleDateFormat) dateFormat; else return new SimpleDateFormat("dd.MM.yyyy", facesContext.getViewRoot().getLocale()); } } }