/** * 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.servlet.taglib; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; import org.apache.commons.lang.StringUtils; import org.apache.struts.taglib.TagUtils; import org.fenixedu.academic.domain.Holiday; import org.fenixedu.academic.domain.Lesson; import org.fenixedu.academic.util.DayType; import org.fenixedu.academic.util.Month; import org.fenixedu.academic.util.MultiLanguageString; import org.fenixedu.academic.util.renderer.GanttDiagram; import org.fenixedu.academic.util.renderer.GanttDiagram.ViewType; import org.fenixedu.academic.util.renderer.GanttDiagramEvent; import org.joda.time.DateMidnight; import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.Interval; import org.joda.time.LocalDate; import org.joda.time.YearMonthDay; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class GanttDiagramTagLib extends TagSupport { private static final Logger logger = LoggerFactory.getLogger(GanttDiagramTagLib.class); private static final String F = "F"; private static final String S = "S"; private static final String D = "D"; private static final String EMPTY_TD_BAR = "emptytdbar"; private static final String TD_BAR = "tdbar"; private static int MONDAY_IN_JODA_TIME = 1, TUESDAY_IN_JODA_TIME = 2, WEDNESDAY_IN_JODA_TIME = 3, THURSDAY_IN_JODA_TIME = 4, FRIDAY_IN_JODA_TIME = 5, SATURDAY_IN_JODA_TIME = 6, SUNDAY_IN_JODA_TIME = 7; // Attributes private String ganttDiagram; private String eventUrl; private String eventParameter; private String bundle; private String firstDayParameter; private String monthlyViewUrl; private String weeklyViewUrl; private String dailyViewUrl; private String toWrite = null; private boolean showPeriod = true; private boolean showObservations = true; private boolean toMark = true; private boolean specialDiv = false; private boolean isEventToMarkWeekendsAndHolidays = false; // Auxiliar variables private GanttDiagram ganttDiagramObject; private List<? extends GanttDiagramEvent> events; private HttpServletRequest request; private ViewType viewTypeEnum; private static BigDecimal PX_TO_EM_CONVERSION_DIVISOR = BigDecimal.TEN; private static BigDecimal EMPTY_UNIT = BigDecimal.ZERO; private static int NUMBER_OF_DAY_5_MINUTES = 288; private static int NUMBER_OF_DAY_HALF_HOURS = 48; private static int NUMBER_OF_DAY_HOURS = 24; private static int FIXED_COLUMNS_SIZE_EM = 50; private static int PADDING_LEFT_MULTIPLIER = 15; @Override public int doStartTag() throws JspException { String ganttDiagram = ""; Object object = pageContext.findAttribute(getGanttDiagram()); if (object != null) { setGanttDiagramObject((GanttDiagram) object); setViewTypeEnum(getGanttDiagramObject().getViewType()); setEvents(getGanttDiagramObject().getEvents()); setShowPeriod(isShowPeriod()); setShowObservations(isShowObservations()); setRequest((HttpServletRequest) pageContext.getRequest()); ganttDiagram = generateGanttDiagramString(); } try { pageContext.getOut().print(ganttDiagram); } catch (IOException e) { logger.error(e.getMessage(), e); } return SKIP_BODY; } private String generateGanttDiagramString() throws JspException { switch (getViewTypeEnum()) { case TOTAL: return generateGanttDiagramInTotalMode(convertToEm(getGanttDiagramObject().getMonthsDaysSize())).toString(); case MONTHLY_TOTAL: return generateGanttDiagramInTotalMode(convertToEm(getGanttDiagramObject().getMonthsDaysSize())).toString(); case MONTHLY: return generateGanttDiagramInTimeMode( BigDecimal.valueOf(getGanttDiagramObject().getDays().size()).multiply(convertToEm(NUMBER_OF_DAY_HOURS))) .toString(); case WEEKLY: return generateGanttDiagramInTimeMode(BigDecimal.valueOf(7).multiply(convertToEm(NUMBER_OF_DAY_HALF_HOURS))) .toString(); case DAILY: return generateGanttDiagramInTimeMode(convertToEm(NUMBER_OF_DAY_5_MINUTES)).toString(); case YEAR_DAILY: return generateGanttDiagramInTimeMode( BigDecimal.valueOf(getGanttDiagramObject().getDays().size()).multiply(convertToEm(NUMBER_OF_DAY_HOURS))) .toString(); default: return ""; } } private StringBuilder generateGanttDiagramInTimeMode(BigDecimal tableWidth) throws JspException { StringBuilder builder = new StringBuilder(); if (!getEvents().isEmpty()) { if (isShowPeriod() && isShowObservations()) { builder.append("<table style=\"width:").append(tableWidth.add(BigDecimal.valueOf(FIXED_COLUMNS_SIZE_EM))) .append("em;\" class=\"tcalendar thlight\">"); } else { builder.append("<table class=\"tcalendar thlight\">"); } generateHeaders(builder); int numberOfUnits = getNumberOfUnits(); String selectedEvent = getRequest().getParameter(getEventParameter()); Object selectedEventObject = getRequest().getAttribute(getEventParameter()); for (GanttDiagramEvent event : getEvents()) { String eventUrl = getRequest().getContextPath() + getEventUrl() + "&" + getEventParameter() + "=" + event.getGanttDiagramEventIdentifier(); if (event.getGanttDiagramEventUrlAddOns() != null) { eventUrl = eventUrl.concat(event.getGanttDiagramEventUrlAddOns()); } final MultiLanguageString diagramEventName = event.getGanttDiagramEventName(); String eventName = diagramEventName == null ? "" : diagramEventName.getContent(); String paddingStyle = "padding-left:" + event.getGanttDiagramEventOffset() * PADDING_LEFT_MULTIPLIER + "px"; if (event.getGanttDiagramEventIdentifier().equals(selectedEvent) || (selectedEventObject != null && event.getGanttDiagramEventIdentifier().equals( selectedEventObject.toString()))) { builder.append("<tr class=\"selected\">"); } else { builder.append("<tr>"); } if (getViewTypeEnum() == ViewType.YEAR_DAILY) { builder.append("<td class=\"padded\">").append("<div class=\"nowrap\">"); builder.append("<span style=\"").append(paddingStyle).append("\" title=\"").append(eventName).append("\">"); builder.append("<a href=\"").append(eventUrl).append("&month=") .append(Month.values()[event.getGanttDiagramEventMonth() - 1].toString()).append("\">") .append(eventName); } else { builder.append("<td class=\"padded\">").append( "<div style=\"overflow:hidden; width: 14.5em;\" class=\"nowrap\">"); builder.append("<span style=\"").append(paddingStyle).append("\" title=\"").append(eventName).append("\">"); builder.append("<a href=\"").append(eventUrl).append("\">").append(eventName); } builder.append("</a></span></div></td>"); for (DateTime day : getGanttDiagramObject().getDays()) { int startIndex = 0, endIndex = 0; int dayOfMonth = day.getDayOfMonth(); int monthOfYear = day.getMonthOfYear(); if (getViewTypeEnum() == ViewType.YEAR_DAILY) { monthOfYear = event.getGanttDiagramEventMonth(); } int year = day.getYear(); YearMonthDay yearMonthDay = new YearMonthDay(year, monthOfYear, 1); isEventToMarkWeekendsAndHolidays = event.isGanttDiagramEventToMarkWeekendsAndHolidays(); if (!isEventToMarkWeekendsAndHolidays) { builder.append("<td style=\"width: ").append(convertToEm(numberOfUnits)) .append("em;\"><div style=\"position: relative;\">"); } if (getViewTypeEnum() == ViewType.YEAR_DAILY) { if (dayOfMonth > yearMonthDay.plusMonths(1).minusDays(1).getDayOfMonth()) { addEmptyDiv(builder); builder.append("</div></td>"); continue; } } specialDiv = false; for (Interval interval : event.getGanttDiagramEventSortedIntervals()) { toWrite = null; toMark = true; LocalDate localDate = yearMonthDay.withDayOfMonth(dayOfMonth).toLocalDate(); if ((event.getGanttDiagramEventDayType(interval) == DayType.SPECIFIC_DAYS) || (event.getGanttDiagramEventDayType(interval) == DayType.WORKDAY)) { if ((localDate.getDayOfWeek() == SATURDAY_IN_JODA_TIME) || (localDate.getDayOfWeek() == SUNDAY_IN_JODA_TIME) || (Holiday.isHoliday(localDate))) { toMark = false; } } if (isEventToMarkWeekendsAndHolidays) { if (Holiday.isHoliday(localDate)) { toWrite = F; } else if (localDate.getDayOfWeek() == SATURDAY_IN_JODA_TIME) { toWrite = S; } else if (localDate.getDayOfWeek() == SUNDAY_IN_JODA_TIME) { toWrite = D; } } if (interval.getStart().getYear() <= year && interval.getEnd().getYear() >= year) { if (interval.getStart().getYear() < year && interval.getEnd().getYear() > year) { addSpecialDiv(builder, convertToEm(numberOfUnits), EMPTY_UNIT); } // Started in same year and Ended after else if (interval.getStart().getYear() == year && interval.getEnd().getYear() > year) { if (interval.getStart().getMonthOfYear() < monthOfYear) { addSpecialDiv(builder, convertToEm(numberOfUnits), EMPTY_UNIT); } else if (interval.getStart().getMonthOfYear() == monthOfYear) { if (interval.getStart().getDayOfMonth() == dayOfMonth) { startIndex = calculateTimeOfDay(interval.getStart()); addSpecialDiv(builder, convertToEm(numberOfUnits - (startIndex - 1)), convertToEm(startIndex - 1)); } else if (interval.getStart().getDayOfMonth() < dayOfMonth) { addSpecialDiv(builder, convertToEm(numberOfUnits), EMPTY_UNIT); } } } // Ended in same year and started before else if (interval.getStart().getYear() < year && interval.getEnd().getYear() == year) { if (interval.getEnd().getMonthOfYear() > monthOfYear) { addSpecialDiv(builder, convertToEm(numberOfUnits), EMPTY_UNIT); } else if (interval.getEnd().getMonthOfYear() == monthOfYear) { if (interval.getEnd().getDayOfMonth() > dayOfMonth) { addSpecialDiv(builder, convertToEm(numberOfUnits), EMPTY_UNIT); } else if (interval.getEnd().getDayOfMonth() == dayOfMonth) { endIndex = calculateTimeOfDay(interval.getEnd()); addSpecialDiv(builder, convertToEm(endIndex), EMPTY_UNIT); } } } // Ended and Started In Same Year else if (interval.getStart().getYear() == year && interval.getEnd().getYear() == year) { if (interval.getStart().getMonthOfYear() <= monthOfYear && interval.getEnd().getMonthOfYear() >= monthOfYear) { if (interval.getStart().getMonthOfYear() == monthOfYear && interval.getEnd().getMonthOfYear() > monthOfYear) { if (interval.getStart().getDayOfMonth() == dayOfMonth) { startIndex = calculateTimeOfDay(interval.getStart()); addSpecialDiv(builder, convertToEm(numberOfUnits - (startIndex - 1)), convertToEm(startIndex - 1)); } else if (interval.getStart().getDayOfMonth() < dayOfMonth) { addSpecialDiv(builder, convertToEm(numberOfUnits), EMPTY_UNIT); } } else if (interval.getStart().getMonthOfYear() < monthOfYear && interval.getEnd().getMonthOfYear() == monthOfYear) { if (interval.getEnd().getDayOfMonth() > dayOfMonth) { addSpecialDiv(builder, convertToEm(numberOfUnits), EMPTY_UNIT); } else if (interval.getEnd().getDayOfMonth() == dayOfMonth) { endIndex = calculateTimeOfDay(interval.getEnd()); addSpecialDiv(builder, convertToEm(endIndex), EMPTY_UNIT); } } else if (interval.getStart().getMonthOfYear() < monthOfYear && interval.getEnd().getMonthOfYear() > monthOfYear) { addSpecialDiv(builder, convertToEm(numberOfUnits), EMPTY_UNIT); } else if (interval.getStart().getMonthOfYear() == monthOfYear && interval.getEnd().getMonthOfYear() == monthOfYear) { if (interval.getStart().getDayOfMonth() <= dayOfMonth && interval.getEnd().getDayOfMonth() >= dayOfMonth) { if (event.isGanttDiagramEventIntervalsLongerThanOneDay() && (interval.getStart().getDayOfMonth() == dayOfMonth || interval.getEnd() .getDayOfMonth() > dayOfMonth)) { startIndex = calculateTimeOfDay(interval.getStart()); addSpecialDiv(builder, convertToEm(numberOfUnits - (startIndex - 1)), convertToEm(startIndex - 1)); } else if (interval.getStart().getDayOfMonth() == dayOfMonth && interval.getEnd().getDayOfMonth() > dayOfMonth) { startIndex = calculateTimeOfDay(interval.getStart()); addSpecialDiv(builder, convertToEm(numberOfUnits - (startIndex - 1)), convertToEm(startIndex - 1)); } else if (interval.getStart().getDayOfMonth() < dayOfMonth && interval.getEnd().getDayOfMonth() == dayOfMonth) { endIndex = calculateTimeOfDay(interval.getEnd()); addSpecialDiv(builder, convertToEm(endIndex), EMPTY_UNIT); } else if (interval.getStart().getDayOfMonth() == dayOfMonth && interval.getEnd().getDayOfMonth() == dayOfMonth) { startIndex = calculateTimeOfDay(interval.getStart()); endIndex = calculateTimeOfDay(interval.getEnd()); if (startIndex == endIndex) { addSpecialDiv(builder, convertToEm(1), convertToEm(startIndex - 1)); } else { addSpecialDiv(builder, convertToEm((endIndex - startIndex) + 1), convertToEm(startIndex - 1)); } } } } } } } } if (!isEventToMarkWeekendsAndHolidays) { builder.append("</div></td>"); } else if (!specialDiv) { builder.append("<td class=\"tdnomark\">"); if (dayOfMonth <= yearMonthDay.plusMonths(1).minusDays(1).getDayOfMonth()) { LocalDate localDate = yearMonthDay.withDayOfMonth(dayOfMonth).toLocalDate(); if (Holiday.isHoliday(localDate)) { builder.append(F); } else if (localDate.getDayOfWeek() == SATURDAY_IN_JODA_TIME) { builder.append("S"); } else if (localDate.getDayOfWeek() == SUNDAY_IN_JODA_TIME) { builder.append("D"); } } builder.append("</td>"); } } if (isShowPeriod()) { builder.append("<td class=\"padded smalltxt\" title=\"").append(event.getGanttDiagramEventPeriod()) .append("\"><div style=\"overflow:hidden;\" class=\"nowrap\">") .append(event.getGanttDiagramEventPeriod()).append("</div></td>"); } if (isShowObservations()) { builder.append("<td class=\"padded smalltxt\">").append(event.getGanttDiagramEventObservations()) .append("</td>"); } builder.append("</tr>"); } insertNextAndBeforeLinks(builder); builder.append("</table>"); } return builder; } private StringBuilder generateGanttDiagramInTotalMode(BigDecimal tableWidth) throws JspException { StringBuilder builder = new StringBuilder(); if (!getEvents().isEmpty()) { if (isShowPeriod() && isShowObservations()) { builder.append("<table style=\"width:").append(tableWidth.add(BigDecimal.valueOf(FIXED_COLUMNS_SIZE_EM))) .append("em;\" class=\"tcalendar thlight\">"); } else { builder.append("<table style=\"width:").append(tableWidth.add(BigDecimal.valueOf(FIXED_COLUMNS_SIZE_EM - 35))) .append("em;\" class=\"tcalendar thlight\">"); } generateHeaders(builder); int scale = getScale(); String selectedEvent = getRequest().getParameter(getEventParameter()); Object selectedEventObject = getRequest().getAttribute(getEventParameter()); for (GanttDiagramEvent event : getEvents()) { String eventUrl = getRequest().getContextPath() + getEventUrl() + "&" + getEventParameter() + "=" + event.getGanttDiagramEventIdentifier(); String eventName = event.getGanttDiagramEventName().getContent(getGanttDiagramObject().getLocale()); String paddingStyle = "padding-left:" + event.getGanttDiagramEventOffset() * PADDING_LEFT_MULTIPLIER + "px"; if (event.getGanttDiagramEventIdentifier().equals(selectedEvent) || (selectedEventObject != null && event.getGanttDiagramEventIdentifier().equals( selectedEventObject.toString()))) { builder.append("<tr class=\"selected\">"); } else { builder.append("<tr>"); } builder.append("<td class=\"padded\">") .append("<div style=\"overflow:hidden; width: 14.5em;\" class=\"nowrap\">"); builder.append("<span style=\"").append(paddingStyle).append("\" title=\"").append(eventName).append("\">"); builder.append("<a href=\"").append(eventUrl).append("\">").append("*").append(eventName); builder.append("</a></span></div></td>"); for (DateTime month : getGanttDiagramObject().getMonths()) { DateTime firstDayOfMonth = (month.getDayOfMonth() != 1) ? month.withDayOfMonth(1) : month; DateTime lastDayOfMonth = firstDayOfMonth.plusMonths(1).minusDays(1); int monthNumberOfDays = Days.daysBetween(firstDayOfMonth, lastDayOfMonth).getDays() + 1; BigDecimal entryDays = EMPTY_UNIT, startDay = EMPTY_UNIT; builder.append("<td style=\"width: ").append(convertToEm(monthNumberOfDays * scale)) .append("em;\"><div style=\"position: relative;\">"); for (Interval interval : event.getGanttDiagramEventSortedIntervals()) { DateMidnight intervalStart = interval.getStart().toDateMidnight(); DateMidnight intervalEnd = interval.getEnd().toDateMidnight(); // Started in this month if (intervalStart.getMonthOfYear() == month.getMonthOfYear() && intervalStart.getYear() == month.getYear()) { // Ended in this month if (interval.getEnd().getMonthOfYear() == month.getMonthOfYear() && intervalEnd.getYear() == month.getYear()) { // Started in first day of this month if (intervalStart.getDayOfMonth() == 1) { // Ended in the last day of this month if (intervalEnd.getDayOfMonth() == monthNumberOfDays) { entryDays = convertToEm((Days.daysBetween(intervalStart, lastDayOfMonth).getDays() + 1) * scale); startDay = convertToEm((intervalStart.getDayOfMonth() - 1) * scale); addSpecialDiv(builder, entryDays, startDay); } // Ended before last day of this month else { entryDays = convertToEm((Days.daysBetween(intervalStart, intervalEnd).getDays() + 1) * scale); startDay = convertToEm((intervalStart.getDayOfMonth() - 1) * scale); addSpecialDiv(builder, entryDays, startDay); } } // Started after first day of this month else { // Ended in the last day of this month if (intervalEnd.getDayOfMonth() == monthNumberOfDays) { entryDays = convertToEm((Days.daysBetween(intervalStart, lastDayOfMonth).getDays() + 1) * scale); startDay = convertToEm((intervalStart.getDayOfMonth() - 1) * scale); addSpecialDiv(builder, entryDays, startDay); } // Ended before last day of this month else { entryDays = convertToEm((Days.daysBetween(intervalStart, intervalEnd).getDays() + 1) * scale); startDay = convertToEm((intervalStart.getDayOfMonth() - 1) * scale); addSpecialDiv(builder, entryDays, startDay); } } } // Ended after this month else { entryDays = convertToEm((Days.daysBetween(intervalStart, lastDayOfMonth).getDays() + 1) * scale); startDay = convertToEm((intervalStart.getDayOfMonth() - 1) * scale); addSpecialDiv(builder, entryDays, startDay); } // Not Started in this month } else { // Started before this month if (intervalStart.getYear() < month.getYear() || (intervalStart.getYear() == month.getYear() && intervalStart.getMonthOfYear() < month .getMonthOfYear())) { // Ended after this month if (intervalEnd.getYear() > month.getYear() || (intervalEnd.getYear() == month.getYear() && intervalEnd.getMonthOfYear() > month .getMonthOfYear())) { entryDays = convertToEm((Days.daysBetween(firstDayOfMonth, lastDayOfMonth).getDays() + 1) * scale); startDay = convertToEm((firstDayOfMonth.getDayOfMonth() - 1) * scale); addSpecialDiv(builder, entryDays, startDay); } else { // Ended in this month if (intervalEnd.getMonthOfYear() == month.getMonthOfYear() && intervalEnd.getYear() == month.getYear()) { entryDays = convertToEm((Days.daysBetween(firstDayOfMonth, intervalEnd).getDays() + 1) * scale); startDay = convertToEm((firstDayOfMonth.getDayOfMonth() - 1) * scale); addSpecialDiv(builder, entryDays, startDay); } } } } } builder.append("</div></td>"); } if (isShowPeriod()) { builder.append("<td class=\"padded smalltxt\" title=\"").append(event.getGanttDiagramEventPeriod()) .append("\"><div style=\"overflow:hidden;\" class=\"nowrap\">") .append(event.getGanttDiagramEventPeriod()).append("</div></td>"); } if (isShowObservations()) { builder.append("<td class=\"padded smalltxt\">").append(event.getGanttDiagramEventObservations()) .append("</td>"); } builder.append("</tr>"); } insertNextAndBeforeLinks(builder); builder.append("</table>"); } return builder; } private void generateHeaders(StringBuilder builder) throws JspException { switch (getViewTypeEnum()) { case WEEKLY: builder.append("<tr>"); builder.append("<th style=\"width: 15em;\" rowspan=\"4\">").append(getMessage("label.ganttDiagram.event")) .append("</th>"); for (Integer year : getGanttDiagramObject().getYearsView().keySet()) { builder.append("<th colspan=\"").append(getGanttDiagramObject().getYearsView().get(year)).append("\">") .append(year).append("</th>"); } if (isShowPeriod()) { builder.append("<th style=\"width: 20em;\" rowspan=\"4\">").append(getMessage("label.ganttDiagram.period")) .append("</th>"); } if (isShowObservations()) { builder.append("<th rowspan=\"4\">").append(getMessage("label.ganttDiagram.observations")).append("</th>"); } builder.append("</tr>"); builder.append("<tr>"); if (!StringUtils.isEmpty(getMonthlyViewUrl())) { String monthlyViewUrl_ = getRequest().getContextPath() + getMonthlyViewUrl() + "&" + getFirstDayParameter() + "="; for (YearMonthDay month : getGanttDiagramObject().getMonthsView().keySet()) { builder.append("<th colspan=\"").append(getGanttDiagramObject().getMonthsView().get(month)).append("\">") .append("<a href=\"").append(monthlyViewUrl_).append(month.toString("ddMMyyyy")).append("\">") .append(month.toString("MMM", getGanttDiagramObject().getLocale())).append("</a>").append("</th>"); } } else { for (YearMonthDay month : getGanttDiagramObject().getMonthsView().keySet()) { builder.append("<th colspan=\"").append(getGanttDiagramObject().getMonthsView().get(month)).append("\">") .append(month.toString("MMM", getGanttDiagramObject().getLocale())).append("</th>"); } } builder.append("</tr>"); builder.append("<tr>"); for (DateTime day : getGanttDiagramObject().getDays()) { builder.append("<th>").append(day.toString("E", getGanttDiagramObject().getLocale())).append("</th>"); } builder.append("</tr>"); builder.append("<tr>"); if (!StringUtils.isEmpty(getDailyViewUrl())) { String dailyViewUrl_ = getRequest().getContextPath() + getDailyViewUrl() + "&" + getFirstDayParameter() + "="; for (DateTime day : getGanttDiagramObject().getDays()) { builder.append("<th>").append("<a href=\"").append(dailyViewUrl_).append(day.toString("ddMMyyyy")) .append("\">").append(day.getDayOfMonth()).append("</a>").append("</th>"); } } else { for (DateTime day : getGanttDiagramObject().getDays()) { builder.append("<th>").append(day.getDayOfMonth()).append("</th>"); } } builder.append("</tr>"); break; case MONTHLY: builder.append("<tr>"); builder.append("<th style=\"width: 15em;\" rowspan=\"2\">").append(getMessage("label.ganttDiagram.event")) .append("</th>"); for (YearMonthDay month : getGanttDiagramObject().getMonthsView().keySet()) { builder.append("<th colspan=\"").append(getGanttDiagramObject().getMonthsView().get(month)).append("\">") .append(month.toString("MMM yyyy", getGanttDiagramObject().getLocale())).append("</th>"); } if (isShowPeriod()) { builder.append("<th style=\"width: 20em;\" rowspan=\"2\">").append(getMessage("label.ganttDiagram.period")) .append("</th>"); } if (isShowObservations()) { builder.append("<th rowspan=\"2\">").append(getMessage("label.ganttDiagram.observations")).append("</th>"); } builder.append("</tr>"); builder.append("<tr>"); if (!StringUtils.isEmpty(getDailyViewUrl())) { String dailyViewUrl_ = getRequest().getContextPath() + getDailyViewUrl() + "&" + getFirstDayParameter() + "="; for (DateTime day : getGanttDiagramObject().getDays()) { builder.append("<th>").append("<a href=\"").append(dailyViewUrl_).append(day.toString("ddMMyyyy")) .append("\">").append(day.getDayOfMonth()).append("</a>").append("</th>"); } } else { for (DateTime day : getGanttDiagramObject().getDays()) { builder.append("<th>").append(day.getDayOfMonth()).append("</th>"); } } builder.append("</tr>"); break; case DAILY: builder.append("<tr>"); builder.append("<th style=\"width: 15em;\">").append(getMessage("label.ganttDiagram.event")).append("</th>"); builder.append("<th>") .append(getGanttDiagramObject().getFirstInstant().toString("E", getGanttDiagramObject().getLocale())) .append(", ").append(getGanttDiagramObject().getFirstInstant().getDayOfMonth()).append(" "); if (!StringUtils.isEmpty(getMonthlyViewUrl())) { String monthlyViewUrl_ = getRequest().getContextPath() + getMonthlyViewUrl() + "&" + getFirstDayParameter() + "="; builder.append("<a href=\"").append(monthlyViewUrl_) .append(getGanttDiagramObject().getFirstInstant().toString("ddMMyyyy")).append("\">") .append(getGanttDiagramObject().getFirstInstant().toString("MMM", getGanttDiagramObject().getLocale())) .append("</a>"); } else { builder.append(getGanttDiagramObject().getFirstInstant().toString("MMM", getGanttDiagramObject().getLocale())); } builder.append(" ").append(getGanttDiagramObject().getFirstInstant().getYear()); if (!StringUtils.isEmpty(getWeeklyViewUrl())) { String weeklyViewUrl_ = getRequest().getContextPath() + getWeeklyViewUrl() + "&" + getFirstDayParameter() + "="; builder.append(" (<a href=\"").append(weeklyViewUrl_) .append(getGanttDiagramObject().getFirstInstant().toString("ddMMyyyy")).append("\">"); builder.append(getMessage("label.ganttDiagram.week")) .append(getGanttDiagramObject().getFirstInstant().getWeekOfWeekyear()).append(")</a>"); } builder.append("</th>"); if (isShowPeriod()) { builder.append("<th style=\"width: 20em;\">").append(getMessage("label.ganttDiagram.period")).append("</th>"); } if (isShowObservations()) { builder.append("<th>").append(getMessage("label.ganttDiagram.observations")).append("</th>"); } builder.append("</tr>"); break; case TOTAL: builder.append("<tr>"); builder.append("<th style=\"width: 15em;\" rowspan=\"2\">").append(getMessage("label.ganttDiagram.event")) .append("</th>"); for (Integer year : getGanttDiagramObject().getYearsView().keySet()) { builder.append("<th colspan=\"").append(getGanttDiagramObject().getYearsView().get(year)).append("\">") .append(year).append("</th>"); } if (isShowPeriod()) { builder.append("<th style=\"width: 20em;\" rowspan=\"2\">").append(getMessage("label.ganttDiagram.period")) .append("</th>"); } if (isShowObservations()) { builder.append("<th rowspan=\"2\">").append(getMessage("label.ganttDiagram.observations")).append("</th>"); } builder.append("</tr>"); builder.append("<tr>"); for (DateTime month : getGanttDiagramObject().getMonths()) { builder.append("<th>").append(month.toString("MMM", getGanttDiagramObject().getLocale())).append("</th>"); } builder.append("</tr>"); break; case MONTHLY_TOTAL: builder.append("<tr>"); builder.append("<th style=\"width: 15em;\">").append(getMessage("label.ganttDiagram.event")).append("</th>"); builder.append("<th>") .append(getGanttDiagramObject().getFirstInstant().toString("MMM", getGanttDiagramObject().getLocale())) .append(" ").append(getGanttDiagramObject().getFirstInstant().getYear()).append("</th>"); if (isShowPeriod()) { builder.append("<th style=\"width: 20em;\">").append(getMessage("label.ganttDiagram.period")).append("</th>"); } if (isShowObservations()) { builder.append("<th>").append(getMessage("label.ganttDiagram.observations")).append("</th>"); } builder.append("</tr>"); break; case YEAR_DAILY: builder.append("<tr>"); builder.append("<th rowspan=\"2\">").append(getMessage("label.ganttDiagram.event")).append("</th>"); for (Integer year : getGanttDiagramObject().getYearsView().keySet()) { builder.append("<th colspan=\"").append(getGanttDiagramObject().getYearsView().get(year)).append("\">") .append(year).append("</th>"); } if (isShowPeriod()) { builder.append("<th style=\"width: 20em;\" rowspan=\"2\">").append(getMessage("label.ganttDiagram.period")) .append("</th>"); } if (isShowObservations()) { builder.append("<th rowspan=\"2\">").append(getMessage("label.ganttDiagram.observations")).append("</th>"); } builder.append("</tr>"); builder.append("<tr>"); if (!StringUtils.isEmpty(getDailyViewUrl())) { String dailyViewUrl_ = getRequest().getContextPath() + getDailyViewUrl() + "&" + getFirstDayParameter() + "="; for (DateTime day : getGanttDiagramObject().getDays()) { builder.append("<th>").append("<a href=\"").append(dailyViewUrl_).append(day.toString("ddMMyyyy")) .append("\">").append(day.getDayOfMonth()).append("</a>").append("</th>"); } } else { for (DateTime day : getGanttDiagramObject().getDays()) { builder.append("<th>").append(day.getDayOfMonth()).append("</th>"); } } builder.append("</tr>"); break; default: break; } } private void insertNextAndBeforeLinks(StringBuilder builder) throws JspException { YearMonthDay firstDay = getGanttDiagramObject().getFirstInstant().toYearMonthDay(); if (firstDay != null) { String nextUrl = ""; String beforeUrl = ""; switch (getViewTypeEnum()) { case WEEKLY: if (!StringUtils.isEmpty(getWeeklyViewUrl())) { nextUrl = getRequest().getContextPath() + getWeeklyViewUrl() + "&" + getFirstDayParameter() + "=" + firstDay.plusDays(Lesson.NUMBER_OF_DAYS_IN_WEEK).toString("ddMMyyyy"); beforeUrl = getRequest().getContextPath() + getWeeklyViewUrl() + "&" + getFirstDayParameter() + "=" + firstDay.minusDays(Lesson.NUMBER_OF_DAYS_IN_WEEK).toString("ddMMyyyy"); builder.append( "<tr><td class=\"tcalendarlinks\"></td><td colspan=\"7\" class=\"acenter tcalendarlinks\"> <span class=\"smalltxt\"><a href=\"") .append(beforeUrl).append("\">").append("<< ").append(getMessage("label.previous.week")) .append("</a>"); builder.append(" , ").append("<a href=\"").append(nextUrl).append("\">") .append(getMessage("label.next.week")).append(" >>").append("</a>") .append("</span></td><td class=\"tcalendarlinks\"></td><td class=\"tcalendarlinks\"></td></tr>"); } break; case DAILY: if (!StringUtils.isEmpty(getDailyViewUrl())) { nextUrl = getRequest().getContextPath() + getDailyViewUrl() + "&" + getFirstDayParameter() + "=" + firstDay.plusDays(1).toString("ddMMyyyy"); beforeUrl = getRequest().getContextPath() + getDailyViewUrl() + "&" + getFirstDayParameter() + "=" + firstDay.minusDays(1).toString("ddMMyyyy"); builder.append( "<tr><td class=\"tcalendarlinks\"></td><td class=\"acenter tcalendarlinks\"><span class=\"smalltxt\"><a href=\"") .append(beforeUrl).append("\">").append("<< ").append(getMessage("label.previous.day")) .append("</a>"); builder.append(" , ").append("<a href=\"").append(nextUrl).append("\">").append(getMessage("label.next.day")) .append(" >>").append("</a>") .append("</span></td><td class=\"tcalendarlinks\"></td><td class=\"tcalendarlinks\"></td></tr>"); } break; case MONTHLY: if (!StringUtils.isEmpty(getMonthlyViewUrl())) { DateTime month = firstDay.toDateTimeAtMidnight(); DateTime firstDayOfMonth = (month.getDayOfMonth() != 1) ? month.withDayOfMonth(1) : month; DateTime lastDayOfMonth = firstDayOfMonth.plusMonths(1).minusDays(1); int monthNumberOfDays = Days.daysBetween(firstDayOfMonth, lastDayOfMonth).getDays() + 1; nextUrl = getRequest().getContextPath() + getMonthlyViewUrl() + "&" + getFirstDayParameter() + "=" + firstDay.plusMonths(1).toString("ddMMyyyy"); beforeUrl = getRequest().getContextPath() + getMonthlyViewUrl() + "&" + getFirstDayParameter() + "=" + firstDay.minusMonths(1).toString("ddMMyyyy"); builder.append("<tr><td class=\"tcalendarlinks\"></td><td colspan=\"").append(monthNumberOfDays) .append("\" class=\"acenter tcalendarlinks\"><span class=\"smalltxt\"><a href=\"").append(beforeUrl) .append("\">").append("<< ").append(getMessage("label.previous.month")).append("</a>"); builder.append(" , ").append("<a href=\"").append(nextUrl).append("\">") .append(getMessage("label.next.month")).append(" >>").append("</a>") .append("</span></td><td class=\"tcalendarlinks\"></td><td class=\"tcalendarlinks\"></td></tr>"); } break; case YEAR_DAILY: if (!StringUtils.isEmpty(getMonthlyViewUrl())) { DateTime month = firstDay.toDateTimeAtMidnight(); DateTime firstDayOfMonth = (month.getDayOfMonth() != 1) ? month.withDayOfMonth(1) : month; DateTime lastDayOfMonth = firstDayOfMonth.plusMonths(1).minusDays(1); int monthNumberOfDays = Days.daysBetween(firstDayOfMonth, lastDayOfMonth).getDays() + 1; nextUrl = getRequest().getContextPath() + getMonthlyViewUrl() + "&" + getFirstDayParameter() + "=" + firstDay.plusMonths(1).toString("ddMMyyyy"); beforeUrl = getRequest().getContextPath() + getMonthlyViewUrl() + "&" + getFirstDayParameter() + "=" + firstDay.minusMonths(1).toString("ddMMyyyy"); builder.append("<tr><td class=\"tcalendarlinks\"></td><td colspan=\"").append(monthNumberOfDays) .append("\" class=\"acenter tcalendarlinks\"><span class=\"smalltxt\"><a href=\"").append(beforeUrl) .append("\">").append("<< ").append(getMessage("label.previous.month")).append("</a>"); builder.append(" , ").append("<a href=\"").append(nextUrl).append("\">") .append(getMessage("label.next.month")).append(" >>").append("</a>") .append("</span></td><td class=\"tcalendarlinks\"></td><td class=\"tcalendarlinks\"></td></tr>"); } break; default: break; } } } private int getScale() { switch (getViewTypeEnum()) { case TOTAL: return 1; case MONTHLY_TOTAL: return 10; default: return 0; } } private int calculateTimeOfDay(DateTime time) { int hourOfDay = time.getHourOfDay(); int minuteOfHour = time.getMinuteOfHour(); switch (getViewTypeEnum()) { case WEEKLY: // unit = 15 minutes int result = (hourOfDay + 1) * 2; if (minuteOfHour <= 30) { return result - 1; } else { return result; } case DAILY: // unit = 5 minutes for (int i = 1, j = 0; j < 60; j += 5, i++) { if (minuteOfHour < j + 5) { return i + (12 * hourOfDay); } } case MONTHLY: // unit = hour of day return hourOfDay; case YEAR_DAILY: // unit = hour of day return hourOfDay; default: return 0; } } private int getNumberOfUnits() { switch (getViewTypeEnum()) { case WEEKLY: return NUMBER_OF_DAY_HALF_HOURS; case DAILY: return NUMBER_OF_DAY_5_MINUTES; case MONTHLY: return NUMBER_OF_DAY_HOURS; case YEAR_DAILY: return NUMBER_OF_DAY_HOURS; default: break; } return 0; } private void addEmptyDiv(StringBuilder builder) { builder.append("<td class=\""); builder.append(EMPTY_TD_BAR); builder.append("\"></td>"); } private void addSpecialDiv(StringBuilder builder, BigDecimal entryDays, BigDecimal startDay) { specialDiv = true; if (isEventToMarkWeekendsAndHolidays) { builder.append("<td"); if (toMark) { builder.append(" class=\""); builder.append(TD_BAR); builder.append("\">"); } else { builder.append(" class=\"tdnomark\">"); } if (toWrite != null) { builder.append(toWrite); } builder.append("</td>"); } else { builder.append("<div style=\"width: ").append(entryDays).append("em; position: absolute; left: "); builder.append(startDay); builder.append("em; top: -0.7em;\" class=\"tdbar\"> </div>"); } } private BigDecimal convertToEm(int value) { return BigDecimal.valueOf(value).divide(PX_TO_EM_CONVERSION_DIVISOR, 2, RoundingMode.HALF_UP); } private String getMessage(String key) throws JspException { String message = getMessageFromBundle(key); return (message != null) ? message : key; } private String getMessageFromBundle(String key) throws JspException { return (getBundle() != null) ? ((TagUtils.getInstance().present(this.pageContext, getBundle(), getGanttDiagramObject() .getLocale().toString(), key)) ? TagUtils.getInstance().message(this.pageContext, getBundle(), getGanttDiagramObject().getLocale().toString(), key) : null) : null; } public String getBundle() { return bundle; } public void setBundle(String bundle) { this.bundle = bundle; } public List<? extends GanttDiagramEvent> getEvents() { return events; } public void setEvents(List<? extends GanttDiagramEvent> events) { this.events = events; } public GanttDiagram getGanttDiagramObject() { return ganttDiagramObject; } public void setGanttDiagramObject(GanttDiagram ganttDiagramObject) { this.ganttDiagramObject = ganttDiagramObject; } public String getEventUrl() { return eventUrl; } public void setEventUrl(String url) { this.eventUrl = url; } public String getEventParameter() { return eventParameter; } public void setEventParameter(String parameter) { this.eventParameter = parameter; } public HttpServletRequest getRequest() { return request; } public void setRequest(HttpServletRequest request) { this.request = request; } public String getGanttDiagram() { return ganttDiagram; } public void setGanttDiagram(String ganttDiagram) { this.ganttDiagram = ganttDiagram; } public ViewType getViewTypeEnum() { return viewTypeEnum; } public void setViewTypeEnum(ViewType viewTypeEnum) { this.viewTypeEnum = viewTypeEnum; } public String getFirstDayParameter() { return firstDayParameter; } public void setFirstDayParameter(String firstDayParameter) { this.firstDayParameter = firstDayParameter; } public String getDailyViewUrl() { return dailyViewUrl; } public void setDailyViewUrl(String dailyViewMode) { this.dailyViewUrl = dailyViewMode; } public String getMonthlyViewUrl() { return monthlyViewUrl; } public void setMonthlyViewUrl(String monthlyViewUrl) { this.monthlyViewUrl = monthlyViewUrl; } public String getWeeklyViewUrl() { return weeklyViewUrl; } public void setWeeklyViewUrl(String weeklyViewUrl) { this.weeklyViewUrl = weeklyViewUrl; } public boolean isShowPeriod() { return showPeriod; } public void setShowPeriod(boolean showPeriod) { this.showPeriod = showPeriod; } public boolean isShowObservations() { return showObservations; } public void setShowObservations(boolean showObservations) { this.showObservations = showObservations; } }