001package org.nuxeo.ecm.agenda; 002 003import java.io.Serializable; 004import java.util.Date; 005import java.util.Map; 006 007import org.apache.commons.lang.StringUtils; 008import org.apache.commons.logging.Log; 009import org.apache.commons.logging.LogFactory; 010import org.joda.time.DateTime; 011import org.joda.time.format.DateTimeFormatter; 012import org.joda.time.format.ISODateTimeFormat; 013import org.nuxeo.ecm.core.api.CoreSession; 014import org.nuxeo.ecm.core.api.DocumentModel; 015import org.nuxeo.ecm.core.api.DocumentModelList; 016import org.nuxeo.ecm.core.api.NuxeoException; 017import org.nuxeo.ecm.core.api.PropertyException; 018import org.nuxeo.ecm.platform.userworkspace.api.UserWorkspaceService; 019import org.nuxeo.runtime.api.Framework; 020import org.nuxeo.runtime.model.DefaultComponent; 021 022/** 023 * @author <a href="mailto:akervern@nuxeo.com">Arnaud Kervern</a> 024 * @since 5.6 025 */ 026public class AgendaComponent extends DefaultComponent implements AgendaService { 027 028 public static final String VEVENT_TYPE = "VEVENT"; 029 030 public static final String SCHEDULABLE_TYPE = "Schedulable"; 031 032 protected static final DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); 033 034 protected static final String QUERY_BETWEEN_DATES = "SELECT * FROM Document WHERE " + "ecm:mixinType = '" 035 + SCHEDULABLE_TYPE + "' " + "AND ((vevent:dtstart BETWEEN TIMESTAMP '%s' AND TIMESTAMP '%s') " 036 + "OR (vevent:dtend BETWEEN TIMESTAMP '%s' AND TIMESTAMP '%s') " 037 + "OR (vevent:dtstart < TIMESTAMP '%s' AND vevent:dtend > TIMESTAMP '%s') " 038 + "OR (vevent:dtstart > TIMESTAMP '%s' AND vevent:dtend < TIMESTAMP '%s')) " 039 + "AND ecm:currentLifeCycleState != 'deleted' " + "AND ecm:isCheckedInVersion = 0 AND ecm:isProxy = 0 " 040 + "AND ecm:path STARTSWITH '%s' ORDER BY vevent:dtstart"; 041 042 protected static final String QUERY_LIMIT = "SELECT * FROM Document WHERE " + "ecm:mixinType = '" 043 + SCHEDULABLE_TYPE + "' " + "AND vevent:dtend > TIMESTAMP '%s' " 044 + "AND ecm:currentLifeCycleState != 'deleted' " + "AND ecm:isCheckedInVersion = 0 AND ecm:isProxy = 0 " 045 + "AND ecm:path STARTSWITH '%s' ORDER BY vevent:dtstart"; 046 047 private static final Log log = LogFactory.getLog(AgendaComponent.class); 048 049 @Override 050 public DocumentModelList listEvents(CoreSession session, String path, Date dtStart, Date dtEnd) 051 { 052 if (dtStart == null) { 053 throw new NuxeoException("Start datetime should not be null"); 054 } 055 if (dtEnd == null) { 056 dtEnd = new Date(dtStart.getTime() + 24 * 3600); 057 } 058 if (dtEnd.before(dtStart)) { 059 throw new NuxeoException("End datetime is before start datetime"); 060 } 061 062 String strStart = formatDate(dtStart); 063 String strEnd = formatDate(dtEnd); 064 return session.query(String.format(QUERY_BETWEEN_DATES, strStart, strEnd, strStart, strEnd, strStart, strEnd, 065 strStart, strEnd, path)); 066 } 067 068 @Override 069 public DocumentModelList listEvents(CoreSession session, String path, int limit) { 070 if (limit <= 0) { 071 throw new NuxeoException("Limit must be greater than 0"); 072 } 073 074 return session.query(String.format(QUERY_LIMIT, formatDate(new Date()), path), limit); 075 } 076 077 protected static String formatDate(Date date) { 078 return new DateTime(date.getTime()).toString(dateTimeFormatter); 079 } 080 081 @Override 082 public DocumentModel createEvent(CoreSession session, String path, Map<String, Serializable> properties) 083 { 084 if (StringUtils.isBlank(path) || "/".equals(path)) { 085 path = getCurrentUserWorkspacePath(session); 086 } 087 DocumentModel doc = session.createDocumentModel(VEVENT_TYPE); 088 doc.setPathInfo(path, null); 089 for (String key : properties.keySet()) { 090 try { 091 doc.setPropertyValue(key, properties.get(key)); 092 } catch (PropertyException pe) { 093 log.info("Trying to set an unknown property " + key); 094 } 095 } 096 return session.createDocument(doc); 097 } 098 099 protected String getCurrentUserWorkspacePath(CoreSession session) { 100 UserWorkspaceService userWorkspaceService = Framework.getLocalService(UserWorkspaceService.class); 101 DocumentModel userPersonalWorkspace = userWorkspaceService.getUserPersonalWorkspace( 102 session.getPrincipal().getName(), session.getRootDocument()); 103 return userPersonalWorkspace.getPathAsString(); 104 } 105}