diff --git a/source/java/org/alfresco/repo/calendar/CalendarHelpersTest.java b/source/java/org/alfresco/repo/calendar/CalendarHelpersTest.java
new file mode 100644
index 0000000000..28488ddc45
--- /dev/null
+++ b/source/java/org/alfresco/repo/calendar/CalendarHelpersTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+package org.alfresco.repo.calendar;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.query.PagingRequest;
+import org.alfresco.query.PagingResults;
+import org.alfresco.repo.policy.BehaviourFilter;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.site.SiteModel;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.service.cmr.calendar.CalendarEntry;
+import org.alfresco.service.cmr.calendar.CalendarEntryDTO;
+import org.alfresco.service.cmr.calendar.CalendarRecurrenceHelper;
+import org.alfresco.service.cmr.calendar.CalendarService;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.MutableAuthenticationService;
+import org.alfresco.service.cmr.security.PermissionService;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.service.cmr.site.SiteInfo;
+import org.alfresco.service.cmr.site.SiteService;
+import org.alfresco.service.cmr.site.SiteVisibility;
+import org.alfresco.service.cmr.tagging.TaggingService;
+import org.alfresco.util.ApplicationContextHelper;
+import org.alfresco.util.PropertyMap;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Test cases for the helpers relating to the {@link CalendarService},
+ * but which don't need a full repo
+ *
+ * @author Nick Burch
+ * @since 4.0
+ */
+public class CalendarHelpersTest
+{
+ private static SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd");
+
+ @Test public void allDayDetection()
+ {
+ Calendar c20110719_0000 = Calendar.getInstance();
+ Calendar c20110719_1000 = Calendar.getInstance();
+ Calendar c20110720_0000 = Calendar.getInstance();
+ Calendar c20110721_0000 = Calendar.getInstance();
+ c20110719_0000.set(2011, 07, 19, 0, 0, 0);
+ c20110719_1000.set(2011, 07, 19, 1, 0, 0);
+ c20110720_0000.set(2011, 07, 20, 0, 0, 0);
+ c20110721_0000.set(2011, 07, 21, 0, 0, 0);
+
+ CalendarEntryDTO entry = new CalendarEntryDTO();
+
+ // Start and end at the same midnight
+ entry.setStart(c20110719_0000.getTime());
+ entry.setEnd( c20110719_0000.getTime());
+ assertTrue(CalendarEntryDTO.isAllDay(entry));
+
+ // Start and end at the next midnight
+ entry.setStart(c20110719_0000.getTime());
+ entry.setEnd( c20110720_0000.getTime());
+ assertTrue(CalendarEntryDTO.isAllDay(entry));
+
+ // Start and end at the midnight after
+ entry.setStart(c20110719_0000.getTime());
+ entry.setEnd( c20110721_0000.getTime());
+ assertTrue(CalendarEntryDTO.isAllDay(entry));
+
+ // One is midnight, one not
+ entry.setStart(c20110719_0000.getTime());
+ entry.setEnd( c20110719_1000.getTime());
+ assertFalse(CalendarEntryDTO.isAllDay(entry));
+
+ entry.setStart(c20110719_1000.getTime());
+ entry.setEnd( c20110720_0000.getTime());
+ assertFalse(CalendarEntryDTO.isAllDay(entry));
+
+ // Neither midnight
+ entry.setStart(c20110719_1000.getTime());
+ entry.setEnd( c20110719_1000.getTime());
+ assertFalse(CalendarEntryDTO.isAllDay(entry));
+ }
+
+ @Test public void dailyRecurrenceDates()
+ {
+ List dates = new ArrayList();
+
+ Calendar currentDate = Calendar.getInstance();
+
+
+ // Dates in the past, get nothing
+ dates.clear();
+ currentDate.set(2011,7-1,19,10,30);
+ RecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, null,
+ date(2011,7,10), date(2011,7,15),
+ true, 1
+ );
+ assertEquals(0, dates.size());
+
+ dates.clear();
+ currentDate.set(2011,7-1,19,10,30);
+ RecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, null,
+ date(2011,7,10), date(2011,7,15),
+ false, 1
+ );
+ assertEquals(0, dates.size());
+
+
+ // From today
+ dates.clear();
+ currentDate.set(2011,7-1,19,10,30);
+ RecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, null,
+ date(2011,7,19), date(2011,7,25),
+ true, 1
+ );
+ assertEquals(1, dates.size());
+ assertEquals("2011-07-19", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2011,7-1,19,10,30);
+ RecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, null,
+ date(2011,7,19), date(2011,7,25),
+ false, 1
+ );
+ assertEquals(6, dates.size());
+ assertEquals("2011-07-19", dateFmt.format(dates.get(0)));
+ assertEquals("2011-07-24", dateFmt.format(dates.get(5)));
+
+
+ // Dates in the future, goes from then
+ dates.clear();
+ currentDate.set(2011,7-1,19,10,30);
+ RecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, null,
+ date(2011,7,20), date(2011,7,30),
+ true, 1
+ );
+ assertEquals(1, dates.size());
+ assertEquals("2011-07-20", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2011,7-1,19,10,30);
+ RecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, null,
+ date(2011,7,20), date(2011,7,30),
+ false, 1
+ );
+ assertEquals(10, dates.size());
+ assertEquals("2011-07-20", dateFmt.format(dates.get(0)));
+ assertEquals("2011-07-29", dateFmt.format(dates.get(9)));
+
+
+ // With no end date but only first, check it behaves
+ dates.clear();
+ currentDate.set(2011,7-1,19,10,30);
+ RecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, null,
+ date(2011,7,19), null,
+ true, 1
+ );
+ assertEquals(1, dates.size());
+ assertEquals("2011-07-19", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2011,7-1,19,10,30);
+ RecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, null,
+ date(2011,7,20), null,
+ true, 1
+ );
+ assertEquals(1, dates.size());
+ assertEquals("2011-07-20", dateFmt.format(dates.get(0)));
+ }
+
+ private static Date date(int year, int month, int day)
+ {
+ return date(year, month, day, 0, 0);
+ }
+ private static Date date(int year, int month, int day, int hour, int minute)
+ {
+ Calendar c = Calendar.getInstance();
+ c.set(year, month-1, day, hour, minute, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ return c.getTime();
+ }
+
+ private static class RecurrenceHelper extends CalendarRecurrenceHelper
+ {
+ protected static void buildDailyRecurrences(Calendar currentDate, List dates,
+ Map params, Date onOrAfter, Date until, boolean firstOnly, int interval)
+ {
+ CalendarRecurrenceHelper.buildDailyRecurrences(
+ currentDate, dates, params, onOrAfter, until, firstOnly, interval);
+ }
+ }
+}
diff --git a/source/java/org/alfresco/service/cmr/calendar/CalendarRecurrenceHelper.java b/source/java/org/alfresco/service/cmr/calendar/CalendarRecurrenceHelper.java
index 538dfb39f1..8caf9d7949 100644
--- a/source/java/org/alfresco/service/cmr/calendar/CalendarRecurrenceHelper.java
+++ b/source/java/org/alfresco/service/cmr/calendar/CalendarRecurrenceHelper.java
@@ -188,236 +188,22 @@ public class CalendarRecurrenceHelper
Calendar currentDate = Calendar.getInstance();
currentDate.setTime(entry.getStart());
- if ("WEEKLY".equals(freq))
- {
- // Get a sorted list of the days it applies to
- List daysOfWeek = new ArrayList();
- for(String dayS : params.get("BYDAY").split(","))
- {
- Integer day = DAY_NAMES_TO_CALENDAR_DAYS.get(dayS);
- if(day == null)
- {
- logger.warn("Invalid day " + dayS);
- }
- else
- {
- daysOfWeek.add(day);
- }
- }
- Collections.sort(daysOfWeek);
-
- // Wind forward
- boolean valid = false;
- while(true)
- {
- // Check each day
- for(int day : daysOfWeek)
- {
- currentDate.set(Calendar.DAY_OF_WEEK, day);
- if(!valid)
- {
- if(currentDate.before(onOrAfter))
- {
- // To early
- }
- else
- {
- // Now in the right range
- valid = true;
- }
- }
- if(valid)
- {
- if(until != null)
- {
- if(currentDate.after(until))
- {
- // Too late
- break;
- }
- }
- dates.add(currentDate.getTime());
- if(firstOnly)
- {
- break;
- }
- }
- }
-
- // Wind on to the next week
- currentDate.set(Calendar.DAY_OF_WEEK, daysOfWeek.get(0));
- currentDate.add(Calendar.DATE, interval*7);
- }
- }
- else if ("DAILY".equals(freq))
+ if ("DAILY".equals(freq))
{
- // Nice and easy
- while(currentDate.before(onOrAfter))
- {
- currentDate.add(Calendar.DATE, 1);
- }
-
- if(firstOnly)
- {
- // Save the first date, if valid
- if(until != null)
- {
- if(currentDate.before(until))
- {
- dates.add(currentDate.getTime());
- }
- }
- else
- {
- dates.add(currentDate.getTime());
- }
- }
- else
- {
- // Run until the end
- while(currentDate.before(until))
- {
- dates.add(currentDate.getTime());
- currentDate.add(Calendar.DATE, 1);
- }
- }
+ buildDailyRecurrences(currentDate, dates, params, onOrAfter, until, firstOnly, interval);
+ }
+ else if ("WEEKLY".equals(freq))
+ {
+ buildWeeklyRecurrences(currentDate, dates, params, onOrAfter, until, firstOnly, interval);
}
-
else if ("MONTHLY".equals(freq))
{
- if (params.get("BYMONTHDAY") != null)
- {
- // eg the 15th of each month
- int dayOfMonth = Integer.parseInt(params.get("BYMONTHDAY"));
- if(currentDate.get(Calendar.DAY_OF_MONTH) < dayOfMonth)
- {
- // Move forward to start
- addMonthToDayOfMonth(currentDate, dayOfMonth);
- }
-
- // Go until in the ok range
- while(currentDate.before(onOrAfter))
- {
- addMonthToDayOfMonth(currentDate, dayOfMonth);
- }
- while(true)
- {
- if(until != null)
- {
- if(currentDate.after(until))
- {
- break;
- }
- }
-
- dates.add(currentDate.getTime());
- if(firstOnly)
- {
- break;
- }
-
- addMonthToDayOfMonth(currentDate, dayOfMonth);
- }
- }
- else if (params.get("BYSETPOS") != null)
- {
- // eg the first Thursday of the month
- int dayOfWeek = DAY_NAMES_TO_CALENDAR_DAYS.get(params.get("BYSETPOS"));
- if(currentDate.get(Calendar.DAY_OF_MONTH) > 8)
- {
- // Move to start, in next month
- addMonthToFirstDayOfWeek(currentDate, dayOfWeek);
- }
- else if(currentDate.get(Calendar.DAY_OF_WEEK) != dayOfWeek)
- {
- // Move forward to start
- Date t = currentDate.getTime();
- currentDate.set(Calendar.DAY_OF_WEEK, dayOfWeek);
- if(currentDate.before(t))
- {
- currentDate.add(Calendar.DATE, 7);
- }
- }
-
- while(currentDate.before(onOrAfter))
- {
- addMonthToFirstDayOfWeek(currentDate, dayOfWeek);
- }
- while(true)
- {
- if(until != null)
- {
- if(currentDate.after(until))
- {
- break;
- }
- }
-
- dates.add(currentDate.getTime());
- if(firstOnly)
- {
- break;
- }
-
- addMonthToFirstDayOfWeek(currentDate, dayOfWeek);
- }
- }
+ buildMonthlyRecurrences(currentDate, dates, params, onOrAfter, until, firstOnly, interval);
}
-
else if ("YEARLY".equals(freq))
{
- int month = Integer.parseInt(params.get("BYMONTH"));
-
- if (params.get("BYMONTHDAY") != null)
- {
- // eg the 2nd of March every year
- int dayOfMonth = Integer.parseInt(params.get("BYMONTHDAY"));
- if(currentDate.get(Calendar.MONTH) == month &&
- currentDate.get(Calendar.DAY_OF_MONTH) == dayOfMonth)
- {
- // Correct start time
- }
- else
- {
- currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + 1);
- currentDate.set(Calendar.MONTH, month);
- currentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
- }
-
- while(currentDate.before(onOrAfter))
- {
- currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + 1);
- currentDate.set(Calendar.MONTH, month);
- currentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
- }
- while(true)
- {
- if(until != null)
- {
- if(currentDate.after(until))
- {
- break;
- }
- }
-
- dates.add(currentDate.getTime());
- if(firstOnly)
- {
- break;
- }
-
- currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + 1);
- currentDate.set(Calendar.MONTH, month);
- currentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
- }
- }
- else
- {
- // eg the first Tuesday in February every year
- int dayOfWeek = DAY_NAMES_TO_CALENDAR_DAYS.get(params.get("BYSETPOS"));
- // TODO
- }
+ buildYearlyRecurrences(currentDate, dates, params, onOrAfter, until, firstOnly, interval);
}
else
{
@@ -434,6 +220,243 @@ public class CalendarRecurrenceHelper
}
}
+ protected static void buildDailyRecurrences(Calendar currentDate, List dates,
+ Map params, Date onOrAfter, Date until, boolean firstOnly, int interval)
+ {
+ // Nice and easy
+ while(currentDate.getTime().before(onOrAfter))
+ {
+ currentDate.add(Calendar.DATE, 1);
+ }
+
+ if(firstOnly)
+ {
+ // Save the first date, if valid
+ if(until != null)
+ {
+ if(currentDate.getTime().before(until))
+ {
+ dates.add(currentDate.getTime());
+ }
+ }
+ else
+ {
+ dates.add(currentDate.getTime());
+ }
+ }
+ else
+ {
+ // Run until the end
+ while(currentDate.getTime().before(until))
+ {
+ dates.add(currentDate.getTime());
+ currentDate.add(Calendar.DATE, 1);
+ }
+ }
+ }
+
+ protected static void buildWeeklyRecurrences(Calendar currentDate, List dates,
+ Map params, Date onOrAfter, Date until, boolean firstOnly, int interval)
+ {
+ // Get a sorted list of the days it applies to
+ List daysOfWeek = new ArrayList();
+ for(String dayS : params.get("BYDAY").split(","))
+ {
+ Integer day = DAY_NAMES_TO_CALENDAR_DAYS.get(dayS);
+ if(day == null)
+ {
+ logger.warn("Invalid day " + dayS);
+ }
+ else
+ {
+ daysOfWeek.add(day);
+ }
+ }
+ Collections.sort(daysOfWeek);
+
+ // Wind forward
+ boolean valid = false;
+ while(true)
+ {
+ // Check each day
+ for(int day : daysOfWeek)
+ {
+ currentDate.set(Calendar.DAY_OF_WEEK, day);
+ if(!valid)
+ {
+ if(currentDate.before(onOrAfter))
+ {
+ // To early
+ }
+ else
+ {
+ // Now in the right range
+ valid = true;
+ }
+ }
+ if(valid)
+ {
+ if(until != null)
+ {
+ if(currentDate.after(until))
+ {
+ // Too late
+ break;
+ }
+ }
+ dates.add(currentDate.getTime());
+ if(firstOnly)
+ {
+ break;
+ }
+ }
+ }
+
+ // Wind on to the next week
+ currentDate.set(Calendar.DAY_OF_WEEK, daysOfWeek.get(0));
+ currentDate.add(Calendar.DATE, interval*7);
+ }
+ }
+
+ protected static void buildMonthlyRecurrences(Calendar currentDate, List dates,
+ Map params, Date onOrAfter, Date until, boolean firstOnly, int interval)
+ {
+ if (params.get("BYMONTHDAY") != null)
+ {
+ // eg the 15th of each month
+ int dayOfMonth = Integer.parseInt(params.get("BYMONTHDAY"));
+ if(currentDate.get(Calendar.DAY_OF_MONTH) < dayOfMonth)
+ {
+ // Move forward to start
+ addMonthToDayOfMonth(currentDate, dayOfMonth);
+ }
+
+ // Go until in the ok range
+ while(currentDate.before(onOrAfter))
+ {
+ addMonthToDayOfMonth(currentDate, dayOfMonth);
+ }
+ while(true)
+ {
+ if(until != null)
+ {
+ if(currentDate.after(until))
+ {
+ break;
+ }
+ }
+
+ dates.add(currentDate.getTime());
+ if(firstOnly)
+ {
+ break;
+ }
+
+ addMonthToDayOfMonth(currentDate, dayOfMonth);
+ }
+ }
+ else if (params.get("BYSETPOS") != null)
+ {
+ // eg the first Thursday of the month
+ int dayOfWeek = DAY_NAMES_TO_CALENDAR_DAYS.get(params.get("BYSETPOS"));
+ if(currentDate.get(Calendar.DAY_OF_MONTH) > 8)
+ {
+ // Move to start, in next month
+ addMonthToFirstDayOfWeek(currentDate, dayOfWeek);
+ }
+ else if(currentDate.get(Calendar.DAY_OF_WEEK) != dayOfWeek)
+ {
+ // Move forward to start
+ Date t = currentDate.getTime();
+ currentDate.set(Calendar.DAY_OF_WEEK, dayOfWeek);
+ if(currentDate.before(t))
+ {
+ currentDate.add(Calendar.DATE, 7);
+ }
+ }
+
+ while(currentDate.before(onOrAfter))
+ {
+ addMonthToFirstDayOfWeek(currentDate, dayOfWeek);
+ }
+ while(true)
+ {
+ if(until != null)
+ {
+ if(currentDate.after(until))
+ {
+ break;
+ }
+ }
+
+ dates.add(currentDate.getTime());
+ if(firstOnly)
+ {
+ break;
+ }
+
+ addMonthToFirstDayOfWeek(currentDate, dayOfWeek);
+ }
+ }
+ }
+
+ protected static void buildYearlyRecurrences(Calendar currentDate, List dates,
+ Map params, Date onOrAfter, Date until, boolean firstOnly, int interval)
+ {
+ int month = Integer.parseInt(params.get("BYMONTH"));
+
+ if (params.get("BYMONTHDAY") != null)
+ {
+ // eg the 2nd of March every year
+ int dayOfMonth = Integer.parseInt(params.get("BYMONTHDAY"));
+ if(currentDate.get(Calendar.MONTH) == month &&
+ currentDate.get(Calendar.DAY_OF_MONTH) == dayOfMonth)
+ {
+ // Correct start time
+ }
+ else
+ {
+ currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + 1);
+ currentDate.set(Calendar.MONTH, month);
+ currentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+ }
+
+ while(currentDate.before(onOrAfter))
+ {
+ currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + 1);
+ currentDate.set(Calendar.MONTH, month);
+ currentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+ }
+ while(true)
+ {
+ if(until != null)
+ {
+ if(currentDate.after(until))
+ {
+ break;
+ }
+ }
+
+ dates.add(currentDate.getTime());
+ if(firstOnly)
+ {
+ break;
+ }
+
+ currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + 1);
+ currentDate.set(Calendar.MONTH, month);
+ currentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+ }
+ }
+ else
+ {
+ // eg the first Tuesday in February every year
+ int dayOfWeek = DAY_NAMES_TO_CALENDAR_DAYS.get(params.get("BYSETPOS"));
+ // TODO
+ }
+ }
+
+
private static void addMonthToDayOfMonth(Calendar c, int dayOfMonth)
{
// Set it to the 1st