package org.opencustomer.db; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import org.apache.log4j.Logger; import org.opencustomer.db.vo.calendar.CalendarVO; import org.opencustomer.db.vo.calendar.EventCalendarVO; import org.opencustomer.db.vo.calendar.EventVO; import org.opencustomer.db.vo.calendar.EventVO.RecurrenceInWeek; import org.opencustomer.framework.util.DateUtility; import org.opencustomer.webapp.module.calendar.util.EventBean; public final class EventUtility { private static final Logger log = Logger.getLogger(EventUtility.class); public static Date calculateRecurrenceEndDate(EventVO event) { Date recurrenceEndDate = event.getStartDate(); CalendarVO calendar = null; for(EventCalendarVO vo : event.getEventCalendars()) { if(vo.getParticipiantType().equals(EventCalendarVO.ParticipiantType.HOST)) { calendar = vo.getCalendar(); } } if(!EventVO.RecurrenceType.NONE.equals(event.getRecurrenceType()) && !EventVO.RecurrenceType.FOREVER.equals(event.getRecurrenceType())) { List<EventBean> beans = calculateRecurrences(calendar, null, event, false); for(EventBean bean : beans) { if(bean.getEndDate().after(recurrenceEndDate)) recurrenceEndDate = bean.getEndDate(); } } else recurrenceEndDate = null; return recurrenceEndDate; } public static List<EventBean> calculateRecurrences(CalendarVO myCalendar, Date endDate, EventVO event, boolean readable) { if(log.isDebugEnabled()) log.debug("calculate recurrences for "+event); List<EventBean> list = new ArrayList<EventBean>(); long duration = event.getEndDate().getTime()-event.getStartDate().getTime(); Calendar calcStartDate = GregorianCalendar.getInstance(); calcStartDate.setTime(event.getStartDate()); int step = event.getRecurrenceCycle(); EventCalendarVO eventCalendar = getEventCalendar(myCalendar, event); // handle days if(EventVO.RecurrenceUnit.DAY.equals(event.getRecurrenceCycleUnit())) { if(EventVO.RecurrenceType.NUMBER_OF_TIMES.equals(event.getRecurrenceType())) { for(int i=1; i<event.getRecurrenceNumberOfTimes(); i++) { calcStartDate.add(Calendar.DAY_OF_MONTH, step); list.add(new EventBean(calcStartDate.getTime(), duration, list.size()+1, event, readable, eventCalendar.getParticipiantType(), eventCalendar.getInvitationStatus())); } } else { Date recurrenceEndDate = endDate; if(EventVO.RecurrenceType.UNTIL_DATE.equals(event.getRecurrenceType())) recurrenceEndDate = event.getRecurrenceUntilDate(); boolean searching = true; while(searching) { calcStartDate.add(Calendar.DAY_OF_MONTH, step); if(calcStartDate.getTime().before(recurrenceEndDate)) list.add(new EventBean(calcStartDate.getTime(), duration, list.size()+1, event, readable, eventCalendar.getParticipiantType(), eventCalendar.getInvitationStatus())); else searching = false; } } } else if(EventVO.RecurrenceUnit.WEEK.equals(event.getRecurrenceCycleUnit())) { if(log.isDebugEnabled()) log.debug("recurrence unit is "+EventVO.RecurrenceUnit.WEEK); int[] day = new int[event.getRecurrenceInWeek().size()]; int[] dayAdd = new int[event.getRecurrenceInWeek().size()]; int week = DateUtility.getCalendar(event.getStartDate(), myCalendar.getFirstDayOfWeek().getDay()).get(Calendar.WEEK_OF_YEAR); Calendar calcDateWeek = GregorianCalendar.getInstance(); calcDateWeek.setTime(event.getStartDate()); calcDateWeek.add(Calendar.DAY_OF_WEEK, 1); // check days between recurrences (max 7 day in sum (-> week)) int pos = 0; for(int i=0; i<7; i++) { RecurrenceInWeek inWeek = RecurrenceInWeek.getForDate(calcDateWeek.getTime()); dayAdd[pos]++; day[pos] = inWeek.getCalendarValue(); if(event.getRecurrenceInWeek().contains(inWeek)) { pos++; // go to next position } if(pos >= dayAdd.length) { pos = 0; // go to zero position } calcDateWeek.roll(Calendar.DAY_OF_WEEK, 1); } if(log.isDebugEnabled()) { StringBuilder builder = new StringBuilder(); for(int i=0; i<day.length; i++) { if(i > 0) builder.append(", "); builder.append("[day:"+day[i]+"-add:"+dayAdd[i]+"]"); } log.debug("day adds: size="+dayAdd.length+" / "+builder.toString()); } if(EventVO.RecurrenceType.NUMBER_OF_TIMES.equals(event.getRecurrenceType())) { int run = 0; for(int i=1; i<event.getRecurrenceNumberOfTimes(); i++) { if(run < dayAdd.length) { calcStartDate.add(Calendar.DAY_OF_WEEK, dayAdd[run]); run++; } if(step > 1) { int newWeek = DateUtility.getCalendar(calcStartDate.getTime(), myCalendar.getFirstDayOfWeek().getDay()).get(Calendar.WEEK_OF_YEAR); if(newWeek != week) calcStartDate.add(Calendar.DAY_OF_WEEK, 7*(step-1)); week = DateUtility.getCalendar(calcStartDate.getTime(), myCalendar.getFirstDayOfWeek().getDay()).get(Calendar.WEEK_OF_YEAR); } if(run >= dayAdd.length) { run = 0; } list.add(new EventBean(calcStartDate.getTime(), duration, list.size()+1, event, readable, eventCalendar.getParticipiantType(), eventCalendar.getInvitationStatus())); } } else { Date recurrenceEndDate = endDate; if(EventVO.RecurrenceType.UNTIL_DATE.equals(event.getRecurrenceType())) recurrenceEndDate = event.getRecurrenceUntilDate(); int run = 0; boolean searching = true; while(searching) { if(run < dayAdd.length) { calcStartDate.add(Calendar.DAY_OF_WEEK, dayAdd[run]); run++; } if(step > 1) { int newWeek = DateUtility.getCalendar(calcStartDate.getTime(), myCalendar.getFirstDayOfWeek().getDay()).get(Calendar.WEEK_OF_YEAR); if(newWeek != week) calcStartDate.add(Calendar.DAY_OF_WEEK, 7*(step-1)); week = DateUtility.getCalendar(calcStartDate.getTime(), myCalendar.getFirstDayOfWeek().getDay()).get(Calendar.WEEK_OF_YEAR); } if(run >= dayAdd.length) { run = 0; } if(calcStartDate.getTime().before(recurrenceEndDate)) list.add(new EventBean(calcStartDate.getTime(), duration, list.size()+1, event, readable, eventCalendar.getParticipiantType(), eventCalendar.getInvitationStatus())); else searching = false; } } } else if(EventVO.RecurrenceUnit.MONTH.equals(event.getRecurrenceCycleUnit())) { if(EventVO.RecurrenceType.NUMBER_OF_TIMES.equals(event.getRecurrenceType())) { for(int i=1; i<event.getRecurrenceNumberOfTimes(); i++) { if(EventVO.RecurrenceInMonth.DAY_OF_MONTH.equals(event.getRecurrenceInMonth())) calcStartDate.add(Calendar.MONTH, step); else { int dayOfWeek = calcStartDate.get(Calendar.DAY_OF_WEEK); int dayOfWeekInMonth = calcStartDate.get(Calendar.DAY_OF_WEEK_IN_MONTH); calcStartDate.add(Calendar.MONTH, step); calcStartDate.set(Calendar.DAY_OF_WEEK, dayOfWeek); calcStartDate.set(Calendar.DAY_OF_WEEK_IN_MONTH, dayOfWeekInMonth); } list.add(new EventBean(calcStartDate.getTime(), duration, list.size()+1, event, readable, eventCalendar.getParticipiantType(), eventCalendar.getInvitationStatus())); } } else { Date recurrenceEndDate = endDate; if(EventVO.RecurrenceType.UNTIL_DATE.equals(event.getRecurrenceType())) recurrenceEndDate = event.getRecurrenceUntilDate(); boolean searching = true; while(searching) { if(EventVO.RecurrenceInMonth.DAY_OF_MONTH.equals(event.getRecurrenceInMonth())) calcStartDate.add(Calendar.MONTH, step); else { int dayOfWeek = calcStartDate.get(Calendar.DAY_OF_WEEK); int dayOfWeekInMonth = calcStartDate.get(Calendar.DAY_OF_WEEK_IN_MONTH); calcStartDate.add(Calendar.MONTH, step); calcStartDate.set(Calendar.DAY_OF_WEEK, dayOfWeek); calcStartDate.set(Calendar.DAY_OF_WEEK_IN_MONTH, dayOfWeekInMonth); } if(calcStartDate.getTime().before(recurrenceEndDate)) list.add(new EventBean(calcStartDate.getTime(), duration, list.size()+1, event, readable, eventCalendar.getParticipiantType(), eventCalendar.getInvitationStatus())); else searching = false; } } } else if(EventVO.RecurrenceUnit.YEAR.equals(event.getRecurrenceCycleUnit())) { if(EventVO.RecurrenceType.NUMBER_OF_TIMES.equals(event.getRecurrenceType())) { for(int i=1; i<event.getRecurrenceNumberOfTimes(); i++) { calcStartDate.add(Calendar.YEAR, step); list.add(new EventBean(calcStartDate.getTime(), duration, list.size()+1, event, readable, eventCalendar.getParticipiantType(), eventCalendar.getInvitationStatus())); } } else { Date recurrenceEndDate = endDate; if(EventVO.RecurrenceType.UNTIL_DATE.equals(event.getRecurrenceType())) recurrenceEndDate = event.getRecurrenceUntilDate(); boolean searching = true; while(searching) { calcStartDate.add(Calendar.YEAR, step); if(calcStartDate.getTime().before(recurrenceEndDate)) list.add(new EventBean(calcStartDate.getTime(), duration, list.size()+1, event, readable, eventCalendar.getParticipiantType(), eventCalendar.getInvitationStatus())); else searching = false; } } } //berechnung der Alarm Zeit fbreske if(event.getReminderDate() != null) { long alarmOffset = event.getStartDate().getTime() - event.getReminderDate().getTime(); for(EventBean eventBean : list) { eventBean.setReminderDate(new Date(eventBean.getStartDate().getTime() - alarmOffset)); } } if(log.isDebugEnabled()) { for(EventBean bean : list) { log.debug("recurrence: "+bean); } } return list; } private static EventCalendarVO getEventCalendar(CalendarVO calendar, EventVO event) { EventCalendarVO eventCalendarVO = null; for(EventCalendarVO vo : event.getEventCalendars()) { if(vo.getCalendar().equals(calendar)) { eventCalendarVO = vo; break; } } return eventCalendarVO; } }