/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition 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; version 3 of the License.
//
// This community edition 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 org.projectforge.plugins.teamcal.event;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Iterator;
import java.util.TimeZone;
import junit.framework.Assert;
import net.fortuna.ical4j.model.Recur;
import org.junit.BeforeClass;
import org.junit.Test;
import org.projectforge.calendar.ICal4JUtils;
import org.projectforge.common.DateFormats;
import org.projectforge.common.DateHelper;
import org.projectforge.common.RecurrenceFrequency;
import org.projectforge.core.Configuration;
import org.projectforge.core.ConfigurationParam;
import org.projectforge.test.AbstractTestBase;
public class TeamEventUtilsTest extends AbstractTestBase
{
@BeforeClass
public static void setUp() throws Exception
{
preInit();
init(true);
final String domain = "projectforge.org";
Configuration.getInstance().forceReload();
Configuration.init4TestMode().put(ConfigurationParam.CALENDAR_DOMAIN, domain);
}
@Test
public void testRRule()
{
testRRule(DateHelper.EUROPE_BERLIN);
testRRule(DateHelper.UTC);
testRRule(TimeZone.getTimeZone("America/Los_Angeles"));
}
@Test
public void recurrenceEvents()
{
final TimeZone timeZone = DateHelper.EUROPE_BERLIN;
{
final TeamEventDO event = createEvent(timeZone, "2011-06-06 11:00", "2011-06-06 12:00", RecurrenceFrequency.WEEKLY, 1, "2013-12-31");
final Collection<TeamEvent> col = TeamEventUtils.getRecurrenceEvents(getDate("2013-10-20", timeZone),
getDate("2013-10-29", timeZone), event, timeZone);
Assert.assertEquals(2, col.size());
final Iterator<TeamEvent> it = col.iterator();
Assert.assertEquals(DateHelper.formatAsUTC(DateHelper.parseIsoTimestamp("2013-10-21 11:00:00.0", timeZone)),
DateHelper.formatAsUTC(it.next().getStartDate()));
Assert.assertEquals(DateHelper.formatAsUTC(DateHelper.parseIsoTimestamp("2013-10-28 11:00:00.0", timeZone)),
DateHelper.formatAsUTC(it.next().getStartDate()));
}
{
final TeamEventDO event = createEvent(timeZone, "2011-03-03 00:00", "2011-03-03 00:00", RecurrenceFrequency.WEEKLY, 2, "2011-04-30")
.setAllDay(true);
final Collection<TeamEvent> col = TeamEventUtils.getRecurrenceEvents(getDate("2011-03-01", timeZone),
getDate("2011-03-31", timeZone), event, timeZone);
Assert.assertEquals(2, col.size());
final Iterator<TeamEvent> it = col.iterator();
Assert.assertEquals(DateHelper.formatAsUTC(DateHelper.parseIsoTimestamp("2011-03-03 00:00:00.0", timeZone)),
DateHelper.formatAsUTC(it.next().getStartDate()));
Assert.assertEquals(DateHelper.formatAsUTC(DateHelper.parseIsoTimestamp("2011-03-17 00:00:00.0", timeZone)),
DateHelper.formatAsUTC(it.next().getStartDate()));
}
}
@Test
public void exDates()
{
testExDates(DateHelper.EUROPE_BERLIN);
testExDates(TimeZone.getTimeZone("Europe/London"));
testExDates(TimeZone.getTimeZone("America/Los_Angeles"));
}
private void testExDates(final TimeZone timeZone)
{
{
final TeamEventDO event = createEvent(timeZone, "2013-03-21 20:00", "2013-03-21 21:30", RecurrenceFrequency.WEEKLY, 1, null);
event.addRecurrenceExDate(parseDateTime("2013-03-28 20:00", timeZone), timeZone);
final Collection<TeamEvent> col = TeamEventUtils.getRecurrenceEvents(getDate("2013-03-01", timeZone),
getDate("2013-04-05", timeZone), event, timeZone);
Assert.assertEquals(2, col.size());
final Iterator<TeamEvent> it = col.iterator();
Assert.assertEquals(DateHelper.formatAsUTC(DateHelper.parseIsoTimestamp("2013-03-21 20:00:00.0", timeZone)),
DateHelper.formatAsUTC(it.next().getStartDate()));
Assert.assertEquals(DateHelper.formatAsUTC(DateHelper.parseIsoTimestamp("2013-04-04 20:00:00.0", timeZone)),
DateHelper.formatAsUTC(it.next().getStartDate()));
}
{
final TeamEventDO event = createEvent(timeZone, "2013-03-21 00:00", "2013-03-21 00:00", RecurrenceFrequency.WEEKLY, 1, null)
.setAllDay(true);
event.addRecurrenceExDate(parseDate("2013-03-28", timeZone), timeZone);
final Collection<TeamEvent> col = TeamEventUtils.getRecurrenceEvents(getDate("2013-03-01", timeZone),
getDate("2013-04-05", timeZone), event, timeZone);
Assert.assertEquals(2, col.size());
final Iterator<TeamEvent> it = col.iterator();
TeamEvent e = it.next();
Assert.assertEquals("2013-03-21 00:00:00.000", DateHelper.formatIsoTimestamp(e.getStartDate(), timeZone));
Assert.assertTrue(e instanceof TeamEventDO);
e = it.next();
Assert.assertEquals("2013-04-04 00:00:00.000", DateHelper.formatIsoTimestamp(e.getStartDate(), timeZone));
Assert.assertFalse(e instanceof TeamEventDO);
}
}
private void testRRule(final TimeZone timeZone)
{
TeamEventDO event = createEvent(timeZone, "2012-12-21 8:30", "2012-12-21 9:00", null, 1, null);
Assert.assertNull(event.getRecurrenceObject());
event = createEvent(timeZone, "2012-12-21 8:30", "2012-12-21 9:00", RecurrenceFrequency.WEEKLY, 1, null);
Assert.assertEquals("FREQ=WEEKLY", event.getRecurrenceRule());
Collection<TeamEvent> events = getRecurrenceEvents("2012-12-01", "2013-01-31", timeZone, event);
assertEvents(events, timeZone, "2012-12-21 08:30", "2012-12-28 08:30", "2013-01-04 08:30", "2013-01-11 08:30", "2013-01-18 08:30",
"2013-01-25 08:30");
event = createEvent(timeZone, "2012-12-21 18:30", "2012-12-22 9:00", RecurrenceFrequency.WEEKLY, 2, "2013-01-31");
Assert.assertEquals("FREQ=WEEKLY;UNTIL=20130131;INTERVAL=2", event.getRecurrenceRule());
events = getRecurrenceEvents("2012-12-01", "2013-03-31", timeZone, event);
assertEvents(events, timeZone, "2012-12-21 18:30", "2013-01-04 18:30", "2013-01-18 18:30");
Assert.assertTrue(events.iterator().next() instanceof TeamEventDO);
}
private TeamEventDO createEvent(final TimeZone timeZone, final String startDate, final String endDate,
final RecurrenceFrequency frequency, final int interval, final String recurrenceUntil)
{
final Timestamp startTimestamp = new Timestamp(parseDateTime(startDate, timeZone).getTime());
final Timestamp endTimestamp = new Timestamp(parseDateTime(endDate, timeZone).getTime());
final TeamEventDO event = new TeamEventDO();
event.setStartDate(startTimestamp).setEndDate(endTimestamp);
final TeamEventRecurrenceData recurData = new TeamEventRecurrenceData(timeZone);
recurData.setFrequency(frequency);
recurData.setInterval(interval);
if (recurrenceUntil != null) {
final java.sql.Date recurrenceUntilDate = new java.sql.Date(DateHelper.parseIsoDate(recurrenceUntil, timeZone).getTime());
recurData.setUntil(recurrenceUntilDate);
}
event.setRecurrence(recurData);
assertRecurrence(event, timeZone, frequency, interval, recurrenceUntil);
return event;
}
private void assertRecurrence(final TeamEventDO event, final TimeZone timeZone, final RecurrenceFrequency frequency, final int interval,
final String utcRecurrenceUntil)
{
final Recur recur = event.getRecurrenceObject();
if (frequency == null) {
Assert.assertNull(recur);
Assert.assertNull(event.getRecurrenceUntil());
return;
}
Assert.assertEquals(frequency, ICal4JUtils.getFrequency(recur));
if (recur.getInterval() > 1) {
Assert.assertEquals(interval, recur.getInterval());
} else {
Assert.assertEquals(-1, recur.getInterval());
}
if (utcRecurrenceUntil == null) {
Assert.assertNull(event.getRecurrenceUntil());
} else {
final String utcString = DateHelper.formatIsoDate(event.getRecurrenceUntil(), DateHelper.UTC);
Assert.assertEquals(utcRecurrenceUntil, utcString);
}
}
private Collection<TeamEvent> getRecurrenceEvents(final String startDateString, final String endDateString, final TimeZone timeZone,
final TeamEventDO event)
{
final java.util.Date startDate = DateHelper.parseIsoDate(startDateString, timeZone);
final java.util.Date endDate = DateHelper.parseIsoDate(endDateString, timeZone);
return TeamEventUtils.getRecurrenceEvents(startDate, endDate, event, timeZone);
}
private java.util.Date parseDateTime(final String dateString, final TimeZone timeZone)
{
final DateFormat df = new SimpleDateFormat(DateFormats.ISO_TIMESTAMP_MINUTES);
df.setTimeZone(timeZone);
try {
return df.parse(dateString);
} catch (final ParseException ex) {
Assert.fail("Can't parse dateString '" + dateString + "': " + ex.getMessage());
return null;
}
}
private java.util.Date parseDate(final String dateString, final TimeZone timeZone)
{
final DateFormat df = new SimpleDateFormat(DateFormats.ISO_DATE);
df.setTimeZone(timeZone);
try {
return df.parse(dateString);
} catch (final ParseException ex) {
Assert.fail("Can't parse dateString '" + dateString + "': " + ex.getMessage());
return null;
}
}
private void assertEvents(final Collection<TeamEvent> events, final TimeZone timeZone, final String... startDates)
{
Assert.assertEquals(startDates.length, events.size());
int i = 0;
final DateFormat df = new SimpleDateFormat(DateFormats.ISO_TIMESTAMP_MINUTES);
df.setTimeZone(timeZone);
for (final TeamEvent event : events) {
if (event instanceof TeamRecurrenceEvent) {
final long duration = ((TeamRecurrenceEvent) event).getMaster().getDuration();
Assert.assertEquals(duration, event.getEndDate().getTime() - event.getStartDate().getTime());
}
final String startDate = startDates[i];
Assert.assertEquals(startDate, df.format(event.getStartDate()));
++i;
}
}
net.fortuna.ical4j.model.Date getDate(final String dateString, final TimeZone timeZone)
{
final java.util.Date date = DateHelper.parseIsoDate(dateString, timeZone);
return ICal4JUtils.getICal4jDate(date, timeZone);
}
}