/** * Copyright © 2002 Instituto Superior Técnico * * This file is part of FenixEdu Academic. * * FenixEdu Academic is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FenixEdu Academic 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>. */ package org.fenixedu.academic.ui.faces.components; import java.io.IOException; import java.text.DateFormatSymbols; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import javax.faces.component.NamingContainer; import javax.faces.component.UIInput; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import org.fenixedu.academic.ui.faces.components.util.CalendarLink; import org.fenixedu.academic.util.DateFormatUtil; public class UIFenixCalendar extends UIInput { public static final String COMPONENT_TYPE = "org.fenixedu.academic.ui.faces.components.UIFenixCalendar"; public static final String COMPONENT_FAMILY = "org.fenixedu.academic.ui.faces.components.UIFenixCalendar"; public UIFenixCalendar() { super(); this.setRendererType(null); } @Override public String getFamily() { return UIFenixCalendar.COMPONENT_FAMILY; } @Override public void encodeBegin(FacesContext context) throws IOException { if (!isRendered()) { return; } ResponseWriter writer = context.getResponseWriter(); Calendar[] begins = getDateArgument("begin"); Calendar[] ends = getDateArgument("end"); for (int i = 0; i < begins.length; i++) { final Calendar begin = begins[i]; final Calendar end = ends[i]; if (begin == null || end == null) { writer.write("<!-- begin and end dates must be specified -->"); } else if (end.before(begin)) { writer.write("<!-- end date must be after begin date -->"); } else { if (begin.get(Calendar.MONTH) == end.get(Calendar.MONTH)) { encodeMonthTable(writer, context, "MONTH" + begin.get(Calendar.MONTH), begin, end); } else { // boolean isFirst = true; for (; begin.before(end); setToFirstDayOfNextMonth(begin)) { Calendar endPeriod = Calendar.getInstance(); endPeriod.setTime(begin.getTime()); endPeriod.set(Calendar.DAY_OF_MONTH, begin.getActualMaximum(Calendar.DAY_OF_MONTH)); if (endPeriod.after(end)) { endPeriod.setTime(end.getTime()); } // if (isFirst) { // isFirst = false; // } else { // writer.append("<br style='page-break-after:always;'/>"); // } encodeMonthTable(writer, context, "MONTH" + begin.get(Calendar.MONTH), begin, endPeriod); } } } } } private Calendar[] getDateArgument(String argumentName) { final Object object = this.getAttributes().get(argumentName); if (object instanceof Calendar) { return new Calendar[] { (Calendar) object }; } else if (object instanceof Date && object != null) { final Calendar calendar = Calendar.getInstance(); calendar.setTime((Date) object); return new Calendar[] { calendar }; } else if (object instanceof Object[]) { final Object[] objects = (Object[]) object; final Calendar[] result = new Calendar[objects.length]; for (int i = 0; i < objects.length; i++) { if (objects[i] instanceof Calendar) { result[i] = (Calendar) objects[i]; } else if (objects[i] instanceof Date && objects[i] != null) { final Calendar calendar = Calendar.getInstance(); calendar.setTime((Date) objects[i]); result[i] = calendar; } else { result[i] = null; } } return result; } else { return new Calendar[0]; } } private static void setToFirstDayOfNextMonth(Calendar date) { if (date.get(Calendar.MONTH) < 11) { date.roll(Calendar.MONTH, true); } else { date.roll(Calendar.MONTH, true); date.roll(Calendar.YEAR, true); } date.set(Calendar.DAY_OF_MONTH, 1); } private void encodeMonthTable(ResponseWriter writer, FacesContext context, String key, Calendar begin, Calendar end) throws IOException { writer.startElement("table", this); writer.writeAttribute("class", "table table-bordered", null); // writer.writeAttribute("class", "fenixCalendar breakafter", null); // writer.writeAttribute("name", getFieldKey(context, key), null); encodeMonthRow(writer, begin, context.getViewRoot().getLocale()); encodeDaysOfWeek(writer, context.getViewRoot().getLocale()); encodeWeeks(writer, begin, end); writer.endElement("table"); writer.startElement("br", this); writer.endElement("br"); } private String getFieldKey(FacesContext context, String key) { return new String(this.getClientId(context) + NamingContainer.SEPARATOR_CHAR + key); } private void encodeMonthRow(ResponseWriter writer, Calendar date, Locale locale) throws IOException { // writer.startElement("tr", this); // writer.startElement("td", this); writer.startElement("caption", this); writer.writeAttribute("style", "font-weight: 600; background: #bbb", null); writer.writeAttribute("class", "text-center", null); // writer.writeAttribute("colspan", 6, null); SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", locale); DateFormatSymbols dfs = sdf.getDateFormatSymbols(); writer.write((dfs.getMonths())[date.get(Calendar.MONTH)]); writer.endElement("caption"); // writer.endElement("td"); // writer.endElement("tr"); } private void encodeDaysOfWeek(ResponseWriter writer, Locale locale) throws IOException { writer.startElement("tr", this); SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", locale); DateFormatSymbols dfs = sdf.getDateFormatSymbols(); encodeDayOfWeek(writer, (dfs.getWeekdays())[Calendar.MONDAY]); encodeDayOfWeek(writer, (dfs.getWeekdays())[Calendar.TUESDAY]); encodeDayOfWeek(writer, (dfs.getWeekdays())[Calendar.WEDNESDAY]); encodeDayOfWeek(writer, (dfs.getWeekdays())[Calendar.THURSDAY]); encodeDayOfWeek(writer, (dfs.getWeekdays())[Calendar.FRIDAY]); encodeDayOfWeek(writer, (dfs.getWeekdays())[Calendar.SATURDAY]); writer.endElement("tr"); } private void encodeDayOfWeek(ResponseWriter writer, String dayLabel) throws IOException { writer.startElement("th", this); writer.write(dayLabel); writer.endElement("th"); } private void encodeWeeks(ResponseWriter writer, Calendar begin, Calendar end) throws IOException { String createLink = (String) this.getAttributes().get("createLink"); String editLinkPage = (String) this.getAttributes().get("editLinkPage"); List<CalendarLink> editLinkParameters = (List<CalendarLink>) this.getAttributes().get("editLinkParameters"); Calendar now = Calendar.getInstance(); Calendar iter = Calendar.getInstance(); iter.setTime(begin.getTime()); for (int beginWeek = begin.get(Calendar.WEEK_OF_MONTH); beginWeek <= end.get(Calendar.WEEK_OF_MONTH); beginWeek++) { writer.startElement("tr", this); writer.writeAttribute("class", "text-right", null); for (int beginDayOfWeek = Calendar.MONDAY; beginDayOfWeek <= Calendar.SATURDAY; beginDayOfWeek++) { if (iter.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { doMonthAwareRoll(iter); } if (iter.after(end)) { writer.startElement("td", this); writer.writeAttribute("style", "width: 16.7%", null); appendExtraLines(writer); writer.endElement("td"); } else if (iter.get(Calendar.DAY_OF_WEEK) == beginDayOfWeek) { writer.startElement("td", this); List<CalendarLink> toDisplay = objectsToDisplayOnThisDay(iter, editLinkParameters); if (toDisplay != null && !toDisplay.isEmpty()) { writer.writeAttribute("style", "background: #e6e6e6; width: 16.7%", null); encodeDay(writer, createLink, now, iter); for (CalendarLink calendarLink : toDisplay) { writer.startElement("br", this); writer.endElement("br"); if (calendarLink.isAsLink()) { writer.startElement("a", this); writer.writeAttribute("style", "text-decoration:none", null); writer.writeAttribute("href", calendarLink.giveLink(editLinkPage), null); } writer.write(calendarLink.getObjectLinkLabel()); if (calendarLink.isAsLink()) { writer.endElement("a"); } } } else { writer.writeAttribute("style", "background: #eee; width: 16.7%", null); encodeDay(writer, createLink, now, iter); } appendExtraLines(writer); writer.endElement("td"); doMonthAwareRoll(iter); } else { writer.startElement("td", this); appendExtraLines(writer); writer.endElement("td"); } } writer.endElement("tr"); } } private void appendExtraLines(final ResponseWriter writer) throws IOException { final String extraLines = (String) this.getAttributes().get("extraLines"); if (extraLines != null && extraLines.length() > 0 && Boolean.valueOf(extraLines).equals(Boolean.TRUE)) { writer.startElement("br", this); writer.endElement("br"); writer.startElement("br", this); writer.endElement("br"); writer.startElement("br", this); writer.endElement("br"); writer.startElement("br", this); writer.endElement("br"); writer.startElement("br", this); writer.endElement("br"); writer.startElement("br", this); writer.endElement("br"); } } private void encodeDay(ResponseWriter writer, String createLink, Calendar now, Calendar iter) throws IOException { if (createLink == null || iter.before(now)) { writer.write(new Integer(iter.get(Calendar.DAY_OF_MONTH)).toString()); } else { writer.startElement("a", this); writer.writeAttribute("style", "text-decoration:none", null); writer.writeAttribute("href", createLink + dateLink(iter), null); writer.write(new Integer(iter.get(Calendar.DAY_OF_MONTH)).toString()); writer.endElement("a"); } } private List<CalendarLink> objectsToDisplayOnThisDay(Calendar iter, List<CalendarLink> editLinkParameters) { List<CalendarLink> result = new ArrayList<CalendarLink>(); for (CalendarLink calendarLink : editLinkParameters) { if (calendarLink.getObjectOccurrence().get(Calendar.DAY_OF_MONTH) == iter.get(Calendar.DAY_OF_MONTH) && calendarLink.getObjectOccurrence().get(Calendar.MONTH) == iter.get(Calendar.MONTH) && calendarLink.getObjectOccurrence().get(Calendar.YEAR) == iter.get(Calendar.YEAR)) { result.add(calendarLink); } } return result; } private void doMonthAwareRoll(Calendar date) { if (date.get(Calendar.DAY_OF_MONTH) < date.getActualMaximum(Calendar.DAY_OF_MONTH)) { date.roll(Calendar.DAY_OF_MONTH, true); } else { date.roll(Calendar.DAY_OF_MONTH, true); date.roll(Calendar.MONTH, true); } } private String dateLink(Calendar date) { final StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("&day="); stringBuilder.append(date.get(Calendar.DAY_OF_MONTH)); stringBuilder.append("&month="); stringBuilder.append((date.get(Calendar.MONTH) + 1)); stringBuilder.append("&year="); stringBuilder.append(date.get(Calendar.YEAR)); stringBuilder.append("&selectedDate="); stringBuilder.append(DateFormatUtil.format("dd/MM/yyyy", date.getTime())); return stringBuilder.toString(); } }