From d1c6383f6e007b167f941a2761bb2de2e2147f64 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Wed, 6 Jul 2011 15:55:15 +0000 Subject: [PATCH] ALF-9156 Flesh out more of the Calendar API, and start on using it for the rest API git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28839 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/calendar/CalendarEntryImpl.java | 54 +++--- .../repo/calendar/CalendarServiceImpl.java | 2 +- .../calendar/CalendarServiceImplTest.java | 157 +++++++++++++++++- .../service/cmr/calendar/CalendarEntry.java | 50 +++++- .../cmr/calendar/CalendarEntryDTO.java | 115 ++++++++++++- 5 files changed, 332 insertions(+), 46 deletions(-) diff --git a/source/java/org/alfresco/repo/calendar/CalendarEntryImpl.java b/source/java/org/alfresco/repo/calendar/CalendarEntryImpl.java index 62703994c7..18d002b255 100644 --- a/source/java/org/alfresco/repo/calendar/CalendarEntryImpl.java +++ b/source/java/org/alfresco/repo/calendar/CalendarEntryImpl.java @@ -21,36 +21,12 @@ package org.alfresco.repo.calendar; import java.io.Serializable; import java.util.Date; import java.util.HashMap; -import java.util.List; import java.util.Map; -import org.alfresco.model.ContentModel; -import org.alfresco.query.CannedQueryFactory; -import org.alfresco.query.CannedQueryResults; -import org.alfresco.query.PagingRequest; -import org.alfresco.query.PagingResults; -import org.alfresco.repo.blog.cannedqueries.DraftsAndPublishedBlogPostsCannedQuery; -import org.alfresco.repo.blog.cannedqueries.DraftsAndPublishedBlogPostsCannedQueryFactory; -import org.alfresco.repo.blog.cannedqueries.GetBlogPostsCannedQuery; -import org.alfresco.repo.blog.cannedqueries.GetBlogPostsCannedQueryFactory; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.calendar.CalendarEntry; import org.alfresco.service.cmr.calendar.CalendarEntryDTO; -import org.alfresco.service.cmr.calendar.CalendarService; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.cmr.site.SiteInfo; -import org.alfresco.service.cmr.site.SiteService; -import org.alfresco.service.cmr.tagging.TaggingService; -import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; -import org.alfresco.util.ParameterCheck; -import org.alfresco.util.registry.NamedObjectRegistry; /** * @author Nick Burch (based on existing webscript controllers in the REST API) @@ -94,7 +70,19 @@ public class CalendarEntryImpl extends CalendarEntryDTO protected static Map toNodeProperties(CalendarEntry entry) { Map properties = new HashMap(); - // TODO + properties.put(CalendarModel.PROP_WHAT, entry.getTitle()); + properties.put(CalendarModel.PROP_DESCRIPTION, entry.getDescription()); + properties.put(CalendarModel.PROP_WHERE, entry.getLocation()); + properties.put(CalendarModel.PROP_FROM_DATE, entry.getStart()); + properties.put(CalendarModel.PROP_TO_DATE, entry.getEnd()); + properties.put(CalendarModel.PROP_RECURRENCE_RULE, entry.getRecurrenceRule()); + properties.put(CalendarModel.PROP_RECURRENCE_LAST_MEETING, entry.getLastRecurrence()); + properties.put(CalendarModel.PROP_IS_OUTLOOK, entry.isOutlook()); + properties.put(CalendarModel.PROP_OUTLOOK_UID, entry.getOutlookUID()); + +// properties.put(CalendarModel.PROP_COLOR, entry.getColor(); + + // TODO Tags, doc folders return properties; } @@ -104,7 +92,19 @@ public class CalendarEntryImpl extends CalendarEntryDTO */ protected static void populate(CalendarEntry entry, Map properties) { - // TODO + entry.setTitle((String)properties.get(CalendarModel.PROP_WHAT)); + entry.setLocation((String)properties.get(CalendarModel.PROP_WHERE)); + entry.setDescription((String)properties.get(CalendarModel.PROP_DESCRIPTION)); + entry.setStart((Date)properties.get(CalendarModel.PROP_FROM_DATE)); + entry.setEnd((Date)properties.get(CalendarModel.PROP_TO_DATE)); + entry.setRecurrenceRule((String)properties.get(CalendarModel.PROP_RECURRENCE_RULE)); + entry.setLastRecurrence((Date)properties.get(CalendarModel.PROP_RECURRENCE_LAST_MEETING)); + entry.setOutlook((Boolean)properties.get(CalendarModel.PROP_IS_OUTLOOK)); + entry.setOutlookUID((String)properties.get(CalendarModel.PROP_OUTLOOK_UID)); + + //entry.setColor(properties.get(CalendarModel.PROP_COLOR)); + + // TODO Tags, doc folders } /** @@ -114,4 +114,4 @@ public class CalendarEntryImpl extends CalendarEntryDTO { populate(this, properties); } -} +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/calendar/CalendarServiceImpl.java b/source/java/org/alfresco/repo/calendar/CalendarServiceImpl.java index 68f4f483ed..48c7c6924c 100644 --- a/source/java/org/alfresco/repo/calendar/CalendarServiceImpl.java +++ b/source/java/org/alfresco/repo/calendar/CalendarServiceImpl.java @@ -43,7 +43,7 @@ import org.apache.commons.logging.LogFactory; */ public class CalendarServiceImpl implements CalendarService { - private static final String CALENDAR_COMPONENT = "calendar"; + protected static final String CALENDAR_COMPONENT = "calendar"; /** * For backwards compatibility with pre-Swift, we are asking the query to give us an accurate total count of how many diff --git a/source/java/org/alfresco/repo/calendar/CalendarServiceImplTest.java b/source/java/org/alfresco/repo/calendar/CalendarServiceImplTest.java index 454d709c81..1999029200 100644 --- a/source/java/org/alfresco/repo/calendar/CalendarServiceImplTest.java +++ b/source/java/org/alfresco/repo/calendar/CalendarServiceImplTest.java @@ -19,6 +19,7 @@ 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; @@ -72,6 +73,7 @@ import org.springframework.context.ApplicationContext; */ public class CalendarServiceImplTest { + private static final String TEST_SITE_PREFIX = "CalendarSiteTest"; private static final ApplicationContext testContext = ApplicationContextHelper.getApplicationContext(); @@ -138,6 +140,8 @@ public class CalendarServiceImplTest entry = new CalendarEntryDTO( "Title", "Description", "Location", new Date(1), new Date(1234) ); + entry.setOutlook(true); + entry.setOutlookUID("12345LookOut!"); // Can't be got until saved assertEquals(null, entry.getSystemName()); @@ -158,24 +162,163 @@ public class CalendarServiceImplTest entry = CALENDAR_SERVICE.createCalendarEntry(CALENDAR_SITE.getShortName(), entry); // Ensure it got a noderef, and the correct site - // TODO - testNodesToTidy.add(entry.getNodeRef()); + assertNotNull(entry.getNodeRef()); + assertNotNull(entry.getSystemName()); - // TODO + NodeRef container = NODE_SERVICE.getPrimaryParent(entry.getNodeRef()).getParentRef(); + NodeRef site = NODE_SERVICE.getPrimaryParent(container).getParentRef(); + assertEquals(CALENDAR_SITE.getNodeRef(), site); + + + // Check the details on the object + assertEquals("Title", entry.getTitle()); + assertEquals("Description", entry.getDescription()); + assertEquals("Location", entry.getLocation()); + assertEquals(1, entry.getStart().getTime()); + assertEquals(1234, entry.getEnd().getTime()); + assertEquals(null, entry.getRecurrenceRule()); + assertEquals(null, entry.getLastRecurrence()); + assertEquals(true, entry.isOutlook()); + assertEquals("12345LookOut!", entry.getOutlookUID()); + + + // Fetch it, and check the details + entry = CALENDAR_SERVICE.getCalendarEntry(CALENDAR_SITE.getShortName(), entry.getSystemName()); + assertEquals("Title", entry.getTitle()); + assertEquals("Description", entry.getDescription()); + assertEquals("Location", entry.getLocation()); + assertEquals(1, entry.getStart().getTime()); + assertEquals(1234, entry.getEnd().getTime()); + assertEquals(null, entry.getRecurrenceRule()); + assertEquals(null, entry.getLastRecurrence()); + assertEquals(true, entry.isOutlook()); + assertEquals("12345LookOut!", entry.getOutlookUID()); + + + // Mark it as done with + testNodesToTidy.add(entry.getNodeRef()); } @Test public void createUpdateDeleteEntry() throws Exception { - // TODO + CalendarEntry entry; + + + // Create an entry + entry = new CalendarEntryDTO( + "Title", "Description", "Location", new Date(1), new Date(1234) + ); + entry.setOutlook(true); + entry.setOutlookUID("12345LookOut!"); + entry = CALENDAR_SERVICE.createCalendarEntry(CALENDAR_SITE.getShortName(), entry); + + + // Check it + assertEquals("Title", entry.getTitle()); + assertEquals("Description", entry.getDescription()); + assertEquals("Location", entry.getLocation()); + assertEquals(1, entry.getStart().getTime()); + assertEquals(1234, entry.getEnd().getTime()); + assertEquals(null, entry.getRecurrenceRule()); + assertEquals(null, entry.getLastRecurrence()); + assertEquals(true, entry.isOutlook()); + assertEquals("12345LookOut!", entry.getOutlookUID()); + + + // Change it + entry.setTitle("New Title"); + entry.setStart(new Date(1234567)); + entry.setEnd(new Date(1294567)); + entry.setRecurrenceRule("1w"); + entry.setLastRecurrence(new Date(1234567)); + entry.setOutlook(false); + entry.setOutlookUID(null); + + CALENDAR_SERVICE.updateCalendarEntry(entry); + + + // Fetch, and check + entry = CALENDAR_SERVICE.getCalendarEntry(CALENDAR_SITE.getShortName(), entry.getSystemName()); + assertEquals("New Title", entry.getTitle()); + assertEquals("Description", entry.getDescription()); + assertEquals("Location", entry.getLocation()); + assertEquals(1234567, entry.getStart().getTime()); + assertEquals(1294567, entry.getEnd().getTime()); + assertEquals("1w", entry.getRecurrenceRule()); + assertEquals(1234567, entry.getLastRecurrence().getTime()); + assertEquals(false, entry.isOutlook()); + assertEquals(null, entry.getOutlookUID()); + + + // Delete it + CALENDAR_SERVICE.deleteCalendarEntry(entry); + + // Check it went + assertEquals(null, CALENDAR_SERVICE.getCalendarEntry(CALENDAR_SITE.getShortName(), entry.getSystemName())); + + + // Finally, check the all day flag detection + Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + // Neither start nor end are at midnight to start + assertEquals(false, CalendarEntryDTO.isAllDay(entry)); + + // Set the start to midnight + entry.setStart(c.getTime()); + assertEquals(false, CalendarEntryDTO.isAllDay(entry)); + + // And end, will then count as all day + entry.setEnd(c.getTime()); + assertEquals(true, CalendarEntryDTO.isAllDay(entry)); } /** * Ensures that when we try to write an entry to the - * container of a new site, it is correctly setup for us + * container of a new site, it is correctly setup for us. + * This test does it's own transactions */ @Test public void newContainerSetup() throws Exception { - // TODO + final String TEST_SITE_NAME = "CalendarTestNewTestSite"; + + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + if(SITE_SERVICE.getSite(TEST_SITE_NAME) != null) + { + SITE_SERVICE.deleteSite(TEST_SITE_NAME); + } + SITE_SERVICE.createSite( + TEST_SITE_PREFIX, TEST_SITE_NAME, "Test", "Test", SiteVisibility.PUBLIC + ); + + // Won't have the container to start with + assertFalse(SITE_SERVICE.hasContainer(TEST_SITE_NAME, CalendarServiceImpl.CALENDAR_COMPONENT)); + + // Create a calendar entry + CalendarEntry entry = new CalendarEntryDTO( + "Title", "Description", "Location", new Date(1), new Date(1234) + ); + CALENDAR_SERVICE.createCalendarEntry(TEST_SITE_NAME, entry); + + // It will now exist + assertTrue(SITE_SERVICE.hasContainer(TEST_SITE_NAME, CalendarServiceImpl.CALENDAR_COMPONENT)); + + // It'll be a tag scope too + NodeRef container = SITE_SERVICE.getContainer(TEST_SITE_NAME, CalendarServiceImpl.CALENDAR_COMPONENT); + assertTrue(TAGGING_SERVICE.isTagScope(container)); + + // Tidy up + SITE_SERVICE.deleteSite(TEST_SITE_NAME); + return null; + } + }); } @Test public void calendarListing() throws Exception @@ -190,7 +333,7 @@ public class CalendarServiceImplTest @Override public SiteInfo execute() throws Throwable { - SiteInfo site = SITE_SERVICE.createSite("CalendarSiteTest", CalendarServiceImplTest.class.getSimpleName() + "_testSite" + System.currentTimeMillis(), + SiteInfo site = SITE_SERVICE.createSite(TEST_SITE_PREFIX, CalendarServiceImplTest.class.getSimpleName() + "_testSite" + System.currentTimeMillis(), "test site title", "test site description", SiteVisibility.PUBLIC); CLASS_TEST_NODES_TO_TIDY.add(site.getNodeRef()); return site; diff --git a/source/java/org/alfresco/service/cmr/calendar/CalendarEntry.java b/source/java/org/alfresco/service/cmr/calendar/CalendarEntry.java index 7831d5c2ef..3ba90c0cb2 100644 --- a/source/java/org/alfresco/service/cmr/calendar/CalendarEntry.java +++ b/source/java/org/alfresco/service/cmr/calendar/CalendarEntry.java @@ -93,15 +93,53 @@ public interface CalendarEntry extends Serializable, PermissionCheckValue { void setEnd(Date end); /** - * @return the Tags associated with the event + * Gets the event recurrence rule. + * TODO Define these */ - List getTags(); + String getRecurrenceRule(); - // TODO All Day events + /** + * Sets the event recurrence rule + * TODO Define these + */ + void setRecurrenceRule(String recurrenceRule); + + /** + * Gets the date of the last instance of this recurring event + */ + Date getLastRecurrence(); + + /** + * Sets the date of the last instance of this recurring event + */ + void setLastRecurrence(Date lastRecurrence); + + /** + * Is this an outlook based event? + */ + boolean isOutlook(); + + /** + * Sets if this is an outlook based event or not + */ + void setOutlook(boolean outlook); + + /** + * Gets the UID used by Outlook for this event. + * See {@link CalendarEntry#isOutlook()} + */ + String getOutlookUID(); + + /** + * Sets the UID used by Outlook for this event. + * When a UID is set, normally the isOutlook flag is set too. + */ + void setOutlookUID(String outlookUID); // TODO Doc folder - // TODO Recurrence - - // TODO Is Outlook + /** + * @return the Tags associated with the event + */ + List getTags(); } diff --git a/source/java/org/alfresco/service/cmr/calendar/CalendarEntryDTO.java b/source/java/org/alfresco/service/cmr/calendar/CalendarEntryDTO.java index 6a5277776e..480fcfb69c 100644 --- a/source/java/org/alfresco/service/cmr/calendar/CalendarEntryDTO.java +++ b/source/java/org/alfresco/service/cmr/calendar/CalendarEntryDTO.java @@ -19,6 +19,7 @@ package org.alfresco.service.cmr.calendar; import java.io.Serializable; +import java.util.Calendar; import java.util.Date; import java.util.List; @@ -39,6 +40,10 @@ public class CalendarEntryDTO implements CalendarEntry, Serializable { private String location; private Date start; private Date end; + private String recurrenceRule; + private Date lastRecurrence; + private boolean isOutlook = false; + private String outlookUID; private List tags; /** @@ -157,6 +162,72 @@ public class CalendarEntryDTO implements CalendarEntry, Serializable { this.end = end; } + /** + * Gets the event recurrence rule. + */ + public String getRecurrenceRule() + { + return recurrenceRule; + } + + /** + * Sets the event recurrence rule + */ + public void setRecurrenceRule(String recurrenceRule) + { + this.recurrenceRule = recurrenceRule; + } + + /** + * Gets the date of the last instance of this recurring event + */ + public Date getLastRecurrence() + { + return lastRecurrence; + } + + /** + * Sets the date of the last instance of this recurring event + */ + public void setLastRecurrence(Date lastRecurrence) + { + this.lastRecurrence = lastRecurrence; + } + + /** + * Is this an outlook based event? + */ + public boolean isOutlook() + { + return isOutlook; + } + + /** + * Sets if this is an outlook based event or not + */ + public void setOutlook(boolean outlook) + { + this.isOutlook = outlook; + } + + /** + * Gets the UID used by Outlook for this event. + * See {@link CalendarEntry#isOutlook()} + */ + public String getOutlookUID() + { + return outlookUID; + } + + /** + * Sets the UID used by Outlook for this event. + * When a UID is set, normally the isOutlook flag is set too. + */ + public void setOutlookUID(String outlookUID) + { + this.outlookUID = outlookUID; + } + /** * @return the Tags associated with the event */ @@ -166,11 +237,45 @@ public class CalendarEntryDTO implements CalendarEntry, Serializable { return tags; } - // TODO All Day events - // TODO Doc folder - // TODO Recurrence - - // TODO Is Outlook + /** + * Does the given {@link CalendarEntry} define an all-day + * event? + * An All Day Event is defined as one starting at midnight + * on a day, and ending at midnight. + * + * For a single day event, the start and end dates should be + * the same, and the times for both are midnight. + * For a multi day event, the start and end times are midnight, + * for the first and last days respectively. + * TODO Timezones! + */ + public static boolean isAllDay(CalendarEntry entry) + { + if(entry.getStart() == null || entry.getEnd() == null) + { + // One or both dates is missing + return false; + } + + Calendar start = Calendar.getInstance(); + Calendar end = Calendar.getInstance(); + start.setTime(entry.getStart()); + end.setTime(entry.getEnd()); + + if(start.get(Calendar.HOUR_OF_DAY) == 0 && + start.get(Calendar.MINUTE) == 0 && + start.get(Calendar.SECOND) == 0 && + end.get(Calendar.HOUR_OF_DAY) == 0 && + end.get(Calendar.MINUTE) == 0 && + end.get(Calendar.SECOND) == 0) + { + // Both midnight, counts as all day + return true; + } + + // In any other case, it isn't an all-day + return false; + } }