package net.sourceforge.fenixedu.util.renderer; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.apache.jcs.access.exception.InvalidArgumentException; import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.Interval; import org.joda.time.YearMonthDay; import pt.utl.ist.fenix.tools.util.i18n.Language; public class GanttDiagram { public final static Comparator INTERVAL_COMPARATOR_BY_BEGIN = new Comparator() { @Override public int compare(Interval o1, Interval o2) { return o1.getStart().compareTo(o2.getStart()); } }; public final static Comparator INTERVAL_COMPARATOR_BY_END = new Comparator() { @Override public int compare(Interval o1, Interval o2) { return o1.getEnd().compareTo(o2.getEnd()); } }; private Locale locale; private List events; private ViewType viewType; private DateTime firstInstant, lastInstant; private Map yearsView; private Map monthsView; private List months, days; public static GanttDiagram getNewTotalGanttDiagram(List events_) throws InvalidArgumentException { return new GanttDiagram(events_, ViewType.TOTAL); } public static GanttDiagram getNewTotalGanttDiagram(List events_, YearMonthDay begin, YearMonthDay end) throws InvalidArgumentException { return new GanttDiagram(events_, ViewType.TOTAL, begin, end); } public static GanttDiagram getNewWeeklyGanttDiagram(List events_, YearMonthDay begin) throws InvalidArgumentException { return new GanttDiagram(events_, ViewType.WEEKLY, begin); } public static GanttDiagram getNewDailyGanttDiagram(List events_, YearMonthDay begin) throws InvalidArgumentException { return new GanttDiagram(events_, ViewType.DAILY, begin); } public static GanttDiagram getNewMonthlyGanttDiagram(List events_, YearMonthDay begin) throws InvalidArgumentException { return new GanttDiagram(events_, ViewType.MONTHLY, begin); } public static GanttDiagram getNewMonthlyTotalGanttDiagram(List events_, YearMonthDay begin) throws InvalidArgumentException { return new GanttDiagram(events_, ViewType.MONTHLY_TOTAL, begin); } public static GanttDiagram getNewYearDailyGanttDiagram(List events_, YearMonthDay begin) throws InvalidArgumentException { return new GanttDiagram(events_, ViewType.YEAR_DAILY, begin); } private GanttDiagram(List events_, ViewType type) throws InvalidArgumentException { setViewType(type); setEvents(events_); init(type, null, null); } private GanttDiagram(List events_, ViewType type, YearMonthDay begin) throws InvalidArgumentException { setViewType(type); setEvents(events_); init(type, begin, null); } private GanttDiagram(List events_, ViewType type, YearMonthDay begin, YearMonthDay end) throws InvalidArgumentException { setViewType(type); setEvents(events_); init(type, begin, end); } private void init(ViewType type, YearMonthDay begin, YearMonthDay end) throws InvalidArgumentException { switch (type) { case TOTAL: calculateFirstAndLastInstantInTotalMode(begin, end); generateYearsViewAndMonths(); break; case MONTHLY_TOTAL: calculateFirstAndLastInstantInMonthlyMode(begin); generateYearsViewAndMonths(); break; case MONTHLY: calculateFirstAndLastInstantInMonthlyMode(begin); generateYearsViewMonthsViewAndDays(); break; case WEEKLY: calculateFirstAndLastInstantInWeeklyMode(begin); generateYearsViewMonthsViewAndDays(); break; case DAILY: calculateFirstAndLastInstantInDailyMode(begin); generateYearsViewMonthsViewAndDays(); break; case YEAR_DAILY: calculateFirstAndLastInstantInMonthlyMode(begin); generateYearsViewMonthsViewAndDays(); break; default: break; } } private void calculateFirstAndLastInstantInMonthlyMode(YearMonthDay begin) throws InvalidArgumentException { if (begin == null) { throw new InvalidArgumentException(); } DateTime beginDateTime = begin.toDateTimeAtMidnight(); beginDateTime = (beginDateTime.getDayOfMonth() != 1) ? beginDateTime.withDayOfMonth(1) : beginDateTime; setFirstInstant(beginDateTime); setLastInstant(beginDateTime.plusMonths(1).minusDays(1)); } private void calculateFirstAndLastInstantInDailyMode(YearMonthDay begin) throws InvalidArgumentException { if (begin == null) { throw new InvalidArgumentException(); } setFirstInstant(begin.toDateTimeAtMidnight()); setLastInstant(begin.toDateTimeAtMidnight()); } private void calculateFirstAndLastInstantInWeeklyMode(YearMonthDay begin) throws InvalidArgumentException { if (begin == null) { throw new InvalidArgumentException(); } DateTime beginDateTime = begin.toDateTimeAtMidnight(); beginDateTime = (beginDateTime.getDayOfWeek() != 1) ? beginDateTime.withDayOfWeek(1) : beginDateTime; setFirstInstant(beginDateTime); setLastInstant(beginDateTime.plusDays(6)); } private void calculateFirstAndLastInstantInTotalMode(YearMonthDay begin, YearMonthDay end) throws InvalidArgumentException { if ((begin != null && end == null) || (end != null && begin == null)) { throw new InvalidArgumentException(); } if (begin == null) { SortedSet allIntervalsSortedByBeginDate = new TreeSet(INTERVAL_COMPARATOR_BY_BEGIN); for (GanttDiagramEvent event : getEvents()) { allIntervalsSortedByBeginDate.addAll(event.getGanttDiagramEventSortedIntervals()); } if (!allIntervalsSortedByBeginDate.isEmpty()) { setFirstInstant(allIntervalsSortedByBeginDate.first().getStart().toDateMidnight().toDateTime()); } SortedSet allIntervalsSortedByEndDate = new TreeSet(INTERVAL_COMPARATOR_BY_END); for (GanttDiagramEvent event : getEvents()) { allIntervalsSortedByEndDate.addAll(event.getGanttDiagramEventSortedIntervals()); } if (!allIntervalsSortedByEndDate.isEmpty()) { setLastInstant(allIntervalsSortedByEndDate.last().getEnd().toDateMidnight().toDateTime()); } } else { setFirstInstant(begin.toDateTimeAtMidnight()); setLastInstant(end.toDateTimeAtMidnight()); } if ((getFirstInstant() != null && getLastInstant() != null) && (getFirstInstant().isAfter(getLastInstant()) || getLastInstant().isBefore(getFirstInstant()))) { throw new InvalidArgumentException(); } } private void generateYearsViewMonthsViewAndDays() { DateTime firstMonthDateTime = getFirstInstant(); DateTime lastMontDateTime = getLastInstant(); if (firstMonthDateTime != null && lastMontDateTime != null) { while ((firstMonthDateTime.getYear() < lastMontDateTime.getYear()) || (firstMonthDateTime.getYear() == lastMontDateTime.getYear() && firstMonthDateTime.getDayOfYear() <= lastMontDateTime .getDayOfYear())) { getDays().add(firstMonthDateTime); YearMonthDay day = firstMonthDateTime.toYearMonthDay().withDayOfMonth(1); if (getMonthsView().containsKey(day)) { getMonthsView().put(day, getMonthsView().get(day) + 1); } else { getMonthsView().put(day, 1); } if (getYearsView().containsKey(Integer.valueOf(firstMonthDateTime.getYear()))) { getYearsView().put(Integer.valueOf(firstMonthDateTime.getYear()), getYearsView().get(Integer.valueOf(firstMonthDateTime.getYear())) + 1); } else { getYearsView().put(Integer.valueOf(firstMonthDateTime.getYear()), 1); } firstMonthDateTime = firstMonthDateTime.plusDays(1); } } } private void generateYearsViewAndMonths() { DateTime firstMonthDateTime = getFirstInstant(); DateTime lastMontDateTime = getLastInstant(); if (firstMonthDateTime != null && lastMontDateTime != null) { while ((firstMonthDateTime.getYear() < lastMontDateTime.getYear()) || (firstMonthDateTime.getYear() == lastMontDateTime.getYear() && firstMonthDateTime.getMonthOfYear() <= lastMontDateTime .getMonthOfYear())) { getMonths().add(firstMonthDateTime); if (getYearsView().containsKey(Integer.valueOf(firstMonthDateTime.getYear()))) { getYearsView().put(Integer.valueOf(firstMonthDateTime.getYear()), getYearsView().get(Integer.valueOf(firstMonthDateTime.getYear())) + 1); } else { getYearsView().put(Integer.valueOf(firstMonthDateTime.getYear()), 1); } firstMonthDateTime = firstMonthDateTime.plusMonths(1); } } } public List getEvents() { return events; } public void setEvents(List events) { this.events = events; } public DateTime getFirstInstant() { return firstInstant; } public void setFirstInstant(DateTime firstInstant) { this.firstInstant = firstInstant; } public DateTime getLastInstant() { return lastInstant; } public void setLastInstant(DateTime lastInstant) { this.lastInstant = lastInstant; } public List getMonths() { if (months == null) { months = new ArrayList(); } return months; } public void setMonths(List months) { this.months = months; } public int getMonthsDaysSize() { int result = 0; for (DateTime month : 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; result += monthNumberOfDays; } return result; } public Map getYearsView() { if (yearsView == null) { yearsView = new TreeMap(); } return yearsView; } public void setYearsView(Map years) { this.yearsView = years; } public Map getMonthsView() { if (monthsView == null) { monthsView = new TreeMap(); } return monthsView; } public void setMonthsView(Map monthsView) { this.monthsView = monthsView; } public ViewType getViewType() { return viewType; } public void setViewType(ViewType viewType) { this.viewType = viewType; } public Locale getLocale() { if (locale == null) { locale = Language.getLocale(); } return locale; } public void setLocale(Locale locale) { this.locale = locale; } public List getDays() { if (days == null) { days = new ArrayList(); } return days; } public void setDays(List days) { this.days = days; } public enum ViewType { TOTAL, MONTHLY, MONTHLY_TOTAL, WEEKLY, DAILY, YEAR_DAILY; } }