1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.calendar.service.impl;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.im.AIMConnector;
28  import com.liferay.portal.im.ICQConnector;
29  import com.liferay.portal.im.MSNConnector;
30  import com.liferay.portal.im.YMConnector;
31  import com.liferay.portal.kernel.cal.DayAndPosition;
32  import com.liferay.portal.kernel.cal.Recurrence;
33  import com.liferay.portal.kernel.cal.TZSRecurrence;
34  import com.liferay.portal.kernel.mail.MailMessage;
35  import com.liferay.portal.kernel.util.ArrayUtil;
36  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
37  import com.liferay.portal.kernel.util.CalendarUtil;
38  import com.liferay.portal.kernel.util.DateFormats;
39  import com.liferay.portal.kernel.util.LocaleUtil;
40  import com.liferay.portal.kernel.util.ReleaseInfo;
41  import com.liferay.portal.kernel.util.StringPool;
42  import com.liferay.portal.kernel.util.StringUtil;
43  import com.liferay.portal.kernel.util.Time;
44  import com.liferay.portal.kernel.util.TimeZoneUtil;
45  import com.liferay.portal.kernel.util.UnmodifiableList;
46  import com.liferay.portal.kernel.util.Validator;
47  import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
48  import com.liferay.portal.model.Company;
49  import com.liferay.portal.model.Contact;
50  import com.liferay.portal.model.ResourceConstants;
51  import com.liferay.portal.model.User;
52  import com.liferay.portal.util.PortalUtil;
53  import com.liferay.portal.util.PortletKeys;
54  import com.liferay.portlet.calendar.EventDurationException;
55  import com.liferay.portlet.calendar.EventEndDateException;
56  import com.liferay.portlet.calendar.EventStartDateException;
57  import com.liferay.portlet.calendar.EventTitleException;
58  import com.liferay.portlet.calendar.job.CheckEventJob;
59  import com.liferay.portlet.calendar.model.CalEvent;
60  import com.liferay.portlet.calendar.model.impl.CalEventImpl;
61  import com.liferay.portlet.calendar.service.base.CalEventLocalServiceBaseImpl;
62  import com.liferay.portlet.calendar.social.CalendarActivityKeys;
63  import com.liferay.portlet.calendar.util.CalUtil;
64  import com.liferay.util.TimeZoneSensitive;
65  import com.liferay.util.servlet.ServletResponseUtil;
66  
67  import java.io.BufferedOutputStream;
68  import java.io.File;
69  import java.io.FileOutputStream;
70  import java.io.FileReader;
71  import java.io.IOException;
72  import java.io.OutputStream;
73  
74  import java.text.DateFormat;
75  
76  import java.util.ArrayList;
77  import java.util.Calendar;
78  import java.util.Date;
79  import java.util.Iterator;
80  import java.util.List;
81  import java.util.Locale;
82  import java.util.Map;
83  import java.util.TimeZone;
84  
85  import javax.mail.internet.InternetAddress;
86  
87  import javax.portlet.PortletPreferences;
88  
89  import net.fortuna.ical4j.data.CalendarBuilder;
90  import net.fortuna.ical4j.data.CalendarOutputter;
91  import net.fortuna.ical4j.data.ParserException;
92  import net.fortuna.ical4j.model.Component;
93  import net.fortuna.ical4j.model.DateTime;
94  import net.fortuna.ical4j.model.Dur;
95  import net.fortuna.ical4j.model.Parameter;
96  import net.fortuna.ical4j.model.Property;
97  import net.fortuna.ical4j.model.PropertyList;
98  import net.fortuna.ical4j.model.Recur;
99  import net.fortuna.ical4j.model.WeekDay;
100 import net.fortuna.ical4j.model.component.VEvent;
101 import net.fortuna.ical4j.model.parameter.Value;
102 import net.fortuna.ical4j.model.property.CalScale;
103 import net.fortuna.ical4j.model.property.Comment;
104 import net.fortuna.ical4j.model.property.DateProperty;
105 import net.fortuna.ical4j.model.property.Description;
106 import net.fortuna.ical4j.model.property.DtEnd;
107 import net.fortuna.ical4j.model.property.DtStart;
108 import net.fortuna.ical4j.model.property.Duration;
109 import net.fortuna.ical4j.model.property.ProdId;
110 import net.fortuna.ical4j.model.property.RRule;
111 import net.fortuna.ical4j.model.property.Summary;
112 import net.fortuna.ical4j.model.property.Uid;
113 import net.fortuna.ical4j.model.property.Version;
114 
115 import org.apache.commons.logging.Log;
116 import org.apache.commons.logging.LogFactory;
117 
118 /**
119  * <a href="CalEventLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
120  *
121  * @author Brian Wing Shun Chan
122  * @author Bruno Farache
123  * @author Samuel Kong
124  *
125  */
126 public class CalEventLocalServiceImpl extends CalEventLocalServiceBaseImpl {
127 
128     public CalEvent addEvent(
129             long userId, long plid, String title, String description,
130             int startDateMonth, int startDateDay, int startDateYear,
131             int startDateHour, int startDateMinute, int endDateMonth,
132             int endDateDay, int endDateYear, int durationHour,
133             int durationMinute, boolean allDay, boolean timeZoneSensitive,
134             String type, boolean repeating, TZSRecurrence recurrence,
135             String remindBy, int firstReminder, int secondReminder,
136             boolean addCommunityPermissions, boolean addGuestPermissions)
137         throws PortalException, SystemException {
138 
139         return addEvent(
140             null, userId, plid, title, description, startDateMonth,
141             startDateDay, startDateYear, startDateHour, startDateMinute,
142             endDateMonth, endDateDay, endDateYear, durationHour, durationMinute,
143             allDay, timeZoneSensitive, type, repeating, recurrence, remindBy,
144             firstReminder, secondReminder,
145             Boolean.valueOf(addCommunityPermissions),
146             Boolean.valueOf(addGuestPermissions), null, null);
147     }
148 
149     public CalEvent addEvent(
150             String uuid, long userId, long plid, String title,
151             String description, int startDateMonth, int startDateDay,
152             int startDateYear, int startDateHour, int startDateMinute,
153             int endDateMonth, int endDateDay, int endDateYear, int durationHour,
154             int durationMinute, boolean allDay, boolean timeZoneSensitive,
155             String type, boolean repeating, TZSRecurrence recurrence,
156             String remindBy, int firstReminder, int secondReminder,
157             boolean addCommunityPermissions, boolean addGuestPermissions)
158         throws PortalException, SystemException {
159 
160         return addEvent(
161             uuid, userId, plid, title, description, startDateMonth,
162             startDateDay, startDateYear, startDateHour, startDateMinute,
163             endDateMonth, endDateDay, endDateYear, durationHour, durationMinute,
164             allDay, timeZoneSensitive, type, repeating, recurrence, remindBy,
165             firstReminder, secondReminder, new Boolean(addCommunityPermissions),
166             new Boolean(addGuestPermissions), null, null);
167     }
168 
169     public CalEvent addEvent(
170             long userId, long plid, String title, String description,
171             int startDateMonth, int startDateDay, int startDateYear,
172             int startDateHour, int startDateMinute, int endDateMonth,
173             int endDateDay, int endDateYear, int durationHour,
174             int durationMinute, boolean allDay, boolean timeZoneSensitive,
175             String type, boolean repeating, TZSRecurrence recurrence,
176             String remindBy, int firstReminder, int secondReminder,
177             String[] communityPermissions, String[] guestPermissions)
178         throws PortalException, SystemException {
179 
180         return addEvent(
181             null, userId, plid, title, description, startDateMonth,
182             startDateDay, startDateYear, startDateHour, startDateMinute,
183             endDateMonth, endDateDay, endDateYear, durationHour, durationMinute,
184             allDay, timeZoneSensitive, type, repeating, recurrence, remindBy,
185             firstReminder, secondReminder, null, null, communityPermissions,
186             guestPermissions);
187     }
188 
189     public CalEvent addEvent(
190             String uuid, long userId, long plid, String title,
191             String description, int startDateMonth, int startDateDay,
192             int startDateYear, int startDateHour, int startDateMinute,
193             int endDateMonth, int endDateDay, int endDateYear, int durationHour,
194             int durationMinute, boolean allDay, boolean timeZoneSensitive,
195             String type, boolean repeating, TZSRecurrence recurrence,
196             String remindBy, int firstReminder, int secondReminder,
197             Boolean addCommunityPermissions, Boolean addGuestPermissions,
198             String[] communityPermissions, String[] guestPermissions)
199         throws PortalException, SystemException {
200 
201         // Event
202 
203         User user = userPersistence.findByPrimaryKey(userId);
204         long groupId = PortalUtil.getScopeGroupId(plid);
205         Date now = new Date();
206 
207         Locale locale = null;
208         TimeZone timeZone = null;
209 
210         if (timeZoneSensitive) {
211             locale = user.getLocale();
212             timeZone = user.getTimeZone();
213         }
214         else {
215             locale = LocaleUtil.getDefault();
216             timeZone = TimeZoneUtil.getDefault();
217         }
218 
219         Calendar startDate = CalendarFactoryUtil.getCalendar(timeZone, locale);
220 
221         startDate.set(Calendar.MONTH, startDateMonth);
222         startDate.set(Calendar.DATE, startDateDay);
223         startDate.set(Calendar.YEAR, startDateYear);
224         startDate.set(Calendar.HOUR_OF_DAY, startDateHour);
225         startDate.set(Calendar.MINUTE, startDateMinute);
226         startDate.set(Calendar.SECOND, 0);
227         startDate.set(Calendar.MILLISECOND, 0);
228 
229         Calendar endDate = CalendarFactoryUtil.getCalendar(timeZone, locale);
230 
231         endDate.set(Calendar.MONTH, endDateMonth);
232         endDate.set(Calendar.DATE, endDateDay);
233         endDate.set(Calendar.YEAR, endDateYear);
234         endDate.set(Calendar.HOUR_OF_DAY, 23);
235         endDate.set(Calendar.MINUTE, 59);
236         endDate.set(Calendar.SECOND, 59);
237         endDate.set(Calendar.MILLISECOND, 999);
238 
239         if (allDay) {
240             startDate.set(Calendar.HOUR_OF_DAY, 0);
241             startDate.set(Calendar.MINUTE, 0);
242 
243             durationHour = 24;
244             durationMinute = 0;
245         }
246 
247         validate(
248             title, startDateMonth, startDateDay, startDateYear, endDateMonth,
249             endDateDay, endDateYear, durationHour, durationMinute, allDay);
250 
251         long eventId = counterLocalService.increment();
252 
253         CalEvent event = calEventPersistence.create(eventId);
254 
255         event.setUuid(uuid);
256         event.setGroupId(groupId);
257         event.setCompanyId(user.getCompanyId());
258         event.setUserId(user.getUserId());
259         event.setUserName(user.getFullName());
260         event.setCreateDate(now);
261         event.setModifiedDate(now);
262         event.setTitle(title);
263         event.setDescription(description);
264         event.setStartDate(startDate.getTime());
265         event.setEndDate(endDate.getTime());
266         event.setDurationHour(durationHour);
267         event.setDurationMinute(durationMinute);
268         event.setAllDay(allDay);
269         event.setTimeZoneSensitive(timeZoneSensitive);
270         event.setType(type);
271         event.setRepeating(repeating);
272         event.setRecurrenceObj(recurrence);
273         event.setRemindBy(remindBy);
274         event.setFirstReminder(firstReminder);
275         event.setSecondReminder(secondReminder);
276 
277         calEventPersistence.update(event, false);
278 
279         // Resources
280 
281         if ((addCommunityPermissions != null) &&
282             (addGuestPermissions != null)) {
283 
284             addEventResources(
285                 event, addCommunityPermissions.booleanValue(),
286                 addGuestPermissions.booleanValue());
287         }
288         else {
289             addEventResources(event, communityPermissions, guestPermissions);
290         }
291 
292         // Social
293 
294         socialActivityLocalService.addActivity(
295             userId, groupId, CalEvent.class.getName(), eventId,
296             CalendarActivityKeys.ADD_EVENT, StringPool.BLANK, 0);
297 
298         // Pool
299 
300         CalEventLocalUtil.clearEventsPool(event.getGroupId());
301 
302         return event;
303     }
304 
305     public void addEventResources(
306             long eventId, boolean addCommunityPermissions,
307             boolean addGuestPermissions)
308         throws PortalException, SystemException {
309 
310         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
311 
312         addEventResources(
313             event, addCommunityPermissions, addGuestPermissions);
314     }
315 
316     public void addEventResources(
317             CalEvent event, boolean addCommunityPermissions,
318             boolean addGuestPermissions)
319         throws PortalException, SystemException {
320 
321         resourceLocalService.addResources(
322             event.getCompanyId(), event.getGroupId(), event.getUserId(),
323             CalEvent.class.getName(), event.getEventId(), false,
324             addCommunityPermissions, addGuestPermissions);
325     }
326 
327     public void addEventResources(
328             long eventId, String[] communityPermissions,
329             String[] guestPermissions)
330         throws PortalException, SystemException {
331 
332         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
333 
334         addEventResources(event, communityPermissions, guestPermissions);
335     }
336 
337     public void addEventResources(
338             CalEvent event, String[] communityPermissions,
339             String[] guestPermissions)
340         throws PortalException, SystemException {
341 
342         resourceLocalService.addModelResources(
343             event.getCompanyId(), event.getGroupId(), event.getUserId(),
344             CalEvent.class.getName(), event.getEventId(), communityPermissions,
345             guestPermissions);
346     }
347 
348     public void checkEvents() throws PortalException, SystemException {
349         Iterator<CalEvent> itr = calEventFinder.findByRemindBy().iterator();
350 
351         while (itr.hasNext()) {
352             CalEvent event = itr.next();
353 
354             User user = userPersistence.fetchByPrimaryKey(event.getUserId());
355 
356             if (user == null) {
357                 deleteEvent(event);
358 
359                 continue;
360             }
361 
362             Calendar now = CalendarFactoryUtil.getCalendar(
363                 user.getTimeZone(), user.getLocale());
364 
365             if (!event.isTimeZoneSensitive()) {
366                 Calendar temp = CalendarFactoryUtil.getCalendar();
367 
368                 temp.setTime(Time.getDate(now));
369 
370                 now = temp;
371             }
372 
373             Calendar startDate = null;
374 
375             if (event.isTimeZoneSensitive()) {
376                 startDate = CalendarFactoryUtil.getCalendar(
377                     user.getTimeZone(), user.getLocale());
378             }
379             else {
380                 startDate = CalendarFactoryUtil.getCalendar();
381             }
382 
383             if (event.isRepeating()) {
384                 double daysToCheck = Math.ceil(
385                     CalEventImpl.REMINDERS[CalEventImpl.REMINDERS.length - 1] /
386                     Time.DAY);
387 
388                 Calendar cal = (Calendar)now.clone();
389 
390                 for (int i = 0; i <= daysToCheck; i++) {
391                     Recurrence recurrence = event.getRecurrenceObj();
392 
393                     Calendar tzICal = CalendarFactoryUtil.getCalendar(
394                         cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
395                         cal.get(Calendar.DATE));
396 
397                     Calendar recurrenceCal = getRecurrenceCal(
398                         cal, tzICal, event);
399 
400                     if (recurrence.isInRecurrence(recurrenceCal)) {
401                         remindUser(event, user, recurrenceCal, now);
402                     }
403 
404                     cal.add(Calendar.DAY_OF_YEAR, 1);
405                 }
406             }
407             else {
408                 startDate.setTime(event.getStartDate());
409 
410                 remindUser(event, user, startDate, now);
411             }
412         }
413     }
414 
415     public void deleteEvent(long eventId)
416         throws PortalException, SystemException {
417 
418         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
419 
420         deleteEvent(event);
421     }
422 
423     public void deleteEvent(CalEvent event)
424         throws PortalException, SystemException {
425 
426         // Pool
427 
428         CalEventLocalUtil.clearEventsPool(event.getGroupId());
429 
430         // Social
431 
432         socialActivityLocalService.deleteActivities(
433             CalEvent.class.getName(), event.getEventId());
434 
435         // Resources
436 
437         resourceLocalService.deleteResource(
438             event.getCompanyId(), CalEvent.class.getName(),
439             ResourceConstants.SCOPE_INDIVIDUAL, event.getEventId());
440 
441         // Event
442 
443         calEventPersistence.remove(event);
444     }
445 
446     public void deleteEvents(long groupId)
447         throws PortalException, SystemException {
448 
449         Iterator<CalEvent> itr = calEventPersistence.findByGroupId(
450             groupId).iterator();
451 
452         while (itr.hasNext()) {
453             CalEvent event = itr.next();
454 
455             deleteEvent(event);
456         }
457     }
458 
459     public File exportEvent(long userId, long eventId)
460         throws PortalException, SystemException {
461 
462         List<CalEvent> events = new ArrayList<CalEvent>();
463 
464         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
465 
466         events.add(event);
467 
468         return exportICal4j(toICalCalendar(userId, events), null);
469     }
470 
471     public File exportGroupEvents(long userId, long plid, String fileName)
472         throws PortalException, SystemException {
473 
474         long groupId = PortalUtil.getScopeGroupId(plid);
475 
476         List<CalEvent> events = calEventPersistence.findByGroupId(groupId);
477 
478         return exportICal4j(toICalCalendar(userId, events), fileName);
479     }
480 
481     public CalEvent getEvent(long eventId)
482         throws PortalException, SystemException {
483 
484         return calEventPersistence.findByPrimaryKey(eventId);
485     }
486 
487     public List<CalEvent> getEvents(
488             long groupId, String type, int start, int end)
489         throws SystemException {
490 
491         if (Validator.isNull(type)) {
492             return calEventPersistence.findByGroupId(groupId, start, end);
493         }
494         else {
495             return calEventPersistence.findByG_T(groupId, type, start, end);
496         }
497     }
498 
499     public List<CalEvent> getEvents(long groupId, Calendar cal)
500         throws SystemException {
501 
502         Map<String, List<CalEvent>> eventsPool =
503             CalEventLocalUtil.getEventsPool(groupId);
504 
505         String key = CalUtil.toString(cal);
506 
507         List<CalEvent> events = eventsPool.get(key);
508 
509         if (events == null) {
510 
511             // Time zone sensitive
512 
513             List<CalEvent> events1 = calEventFinder.findByG_SD(
514                 groupId, CalendarUtil.getGTDate(cal),
515                 CalendarUtil.getLTDate(cal), true);
516 
517             // Time zone insensitive
518 
519             Calendar tzICal = CalendarFactoryUtil.getCalendar(
520                 cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
521                 cal.get(Calendar.DATE));
522 
523             List<CalEvent> events2 = calEventFinder.findByG_SD(
524                 groupId, CalendarUtil.getGTDate(tzICal),
525                 CalendarUtil.getLTDate(tzICal), false);
526 
527             // Create new list
528 
529             events = new ArrayList<CalEvent>();
530 
531             events.addAll(events1);
532             events.addAll(events2);
533 
534             // Add repeating events
535 
536             Iterator<CalEvent> itr = getRepeatingEvents(groupId).iterator();
537 
538             while (itr.hasNext()) {
539                 CalEvent event = itr.next();
540 
541                 TZSRecurrence recurrence = event.getRecurrenceObj();
542 
543                 try {
544 
545                     // LEP-3468
546 
547                     if ((recurrence.getFrequency() !=
548                             Recurrence.NO_RECURRENCE) &&
549                         (recurrence.getInterval() <= 0)) {
550 
551                         recurrence.setInterval(1);
552 
553                         event.setRecurrenceObj(recurrence);
554 
555                         event = calEventPersistence.update(event, false);
556 
557                         recurrence = event.getRecurrenceObj();
558                     }
559 
560                     if (recurrence.isInRecurrence(
561                             getRecurrenceCal(cal, tzICal, event))) {
562 
563                         events.add(event);
564                     }
565                 }
566                 catch (Exception e) {
567                     _log.error(e.getMessage());
568                 }
569             }
570 
571             events = new UnmodifiableList(events);
572 
573             eventsPool.put(key, events);
574         }
575 
576         return events;
577     }
578 
579     public List<CalEvent> getEvents(long groupId, Calendar cal, String type)
580         throws SystemException {
581 
582         List<CalEvent> events = getEvents(groupId, cal);
583 
584         if (Validator.isNull(type)) {
585             return events;
586         }
587         else {
588             events = new ArrayList<CalEvent>(events);
589 
590             Iterator<CalEvent> itr = events.iterator();
591 
592             while (itr.hasNext()) {
593                 CalEvent event = itr.next();
594 
595                 if (!event.getType().equals(type)) {
596                     itr.remove();
597                 }
598             }
599 
600             return events;
601         }
602     }
603 
604     public int getEventsCount(long groupId, String type)
605         throws SystemException {
606 
607         if (Validator.isNull(type)) {
608             return calEventPersistence.countByGroupId(groupId);
609         }
610         else {
611             return calEventPersistence.countByG_T(groupId, type);
612         }
613     }
614 
615     public List<CalEvent> getRepeatingEvents(long groupId)
616         throws SystemException {
617 
618         Map<String, List<CalEvent>> eventsPool =
619             CalEventLocalUtil.getEventsPool(groupId);
620 
621         String key = "recurrence";
622 
623         List<CalEvent> events = eventsPool.get(key);
624 
625         if (events == null) {
626             events = calEventPersistence.findByG_R(groupId, true);
627 
628             events = new UnmodifiableList(events);
629 
630             eventsPool.put(key, events);
631         }
632 
633         return events;
634     }
635 
636     public boolean hasEvents(long groupId, Calendar cal)
637         throws SystemException {
638 
639         return hasEvents(groupId, cal, null);
640     }
641 
642     public boolean hasEvents(long groupId, Calendar cal, String type)
643         throws SystemException {
644 
645         if (getEvents(groupId, cal, type).size() > 0) {
646             return true;
647         }
648         else {
649             return false;
650         }
651     }
652 
653     public void importICal4j(long userId, long plid, File file)
654         throws PortalException, SystemException {
655 
656         try {
657             CalendarBuilder builder = new CalendarBuilder();
658 
659             net.fortuna.ical4j.model.Calendar calendar = builder.build(
660                 new FileReader(file));
661 
662             Iterator<VEvent> itr = calendar.getComponents(
663                 Component.VEVENT).iterator();
664 
665             while (itr.hasNext()) {
666                 VEvent vEvent = itr.next();
667 
668                 importICal4j(userId, plid, vEvent);
669             }
670         }
671         catch (IOException ioe) {
672             throw new SystemException(ioe.getMessage());
673         }
674         catch (ParserException pe) {
675             throw new SystemException(pe.getMessage());
676         }
677     }
678 
679     public CalEvent updateEvent(
680             long userId, long eventId, String title, String description,
681             int startDateMonth, int startDateDay, int startDateYear,
682             int startDateHour, int startDateMinute, int endDateMonth,
683             int endDateDay, int endDateYear, int durationHour,
684             int durationMinute, boolean allDay, boolean timeZoneSensitive,
685             String type, boolean repeating, TZSRecurrence recurrence,
686             String remindBy, int firstReminder, int secondReminder)
687         throws PortalException, SystemException {
688 
689         // Event
690 
691         User user = userPersistence.findByPrimaryKey(userId);
692 
693         Locale locale = null;
694         TimeZone timeZone = null;
695 
696         if (timeZoneSensitive) {
697             locale = user.getLocale();
698             timeZone = user.getTimeZone();
699         }
700         else {
701             locale = LocaleUtil.getDefault();
702             timeZone = TimeZoneUtil.getDefault();
703         }
704 
705         Calendar startDate = CalendarFactoryUtil.getCalendar(timeZone, locale);
706 
707         startDate.set(Calendar.MONTH, startDateMonth);
708         startDate.set(Calendar.DATE, startDateDay);
709         startDate.set(Calendar.YEAR, startDateYear);
710         startDate.set(Calendar.HOUR_OF_DAY, startDateHour);
711         startDate.set(Calendar.MINUTE, startDateMinute);
712         startDate.set(Calendar.SECOND, 0);
713         startDate.set(Calendar.MILLISECOND, 0);
714 
715         Calendar endDate = CalendarFactoryUtil.getCalendar(timeZone, locale);
716 
717         endDate.set(Calendar.MONTH, endDateMonth);
718         endDate.set(Calendar.DATE, endDateDay);
719         endDate.set(Calendar.YEAR, endDateYear);
720         endDate.set(Calendar.HOUR_OF_DAY, 23);
721         endDate.set(Calendar.MINUTE, 59);
722         endDate.set(Calendar.SECOND, 59);
723         endDate.set(Calendar.MILLISECOND, 999);
724 
725         if (allDay) {
726             startDate.set(Calendar.HOUR_OF_DAY, 0);
727             startDate.set(Calendar.MINUTE, 0);
728 
729             durationHour = 24;
730             durationMinute = 0;
731         }
732 
733         validate(
734             title, startDateMonth, startDateDay, startDateYear, endDateMonth,
735             endDateDay, endDateYear, durationHour, durationMinute, allDay);
736 
737         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
738 
739         event.setModifiedDate(new Date());
740         event.setTitle(title);
741         event.setDescription(description);
742         event.setStartDate(startDate.getTime());
743         event.setEndDate(endDate.getTime());
744         event.setDurationHour(durationHour);
745         event.setDurationMinute(durationMinute);
746         event.setAllDay(allDay);
747         event.setTimeZoneSensitive(timeZoneSensitive);
748         event.setType(type);
749         event.setRepeating(repeating);
750         event.setRecurrenceObj(recurrence);
751         event.setRemindBy(remindBy);
752         event.setFirstReminder(firstReminder);
753         event.setSecondReminder(secondReminder);
754 
755         calEventPersistence.update(event, false);
756 
757         // Social
758 
759         socialActivityLocalService.addActivity(
760             userId, event.getGroupId(), CalEvent.class.getName(), eventId,
761             CalendarActivityKeys.UPDATE_EVENT, StringPool.BLANK, 0);
762 
763         // Pool
764 
765         CalEventLocalUtil.clearEventsPool(event.getGroupId());
766 
767         return event;
768     }
769 
770     protected File exportICal4j(
771             net.fortuna.ical4j.model.Calendar cal, String fileName)
772         throws SystemException {
773 
774         OutputStream os = null;
775 
776         try {
777             String extension = ".ics";
778 
779             if (Validator.isNull(fileName)) {
780                 fileName = "liferay.";
781             }
782             else {
783                 int pos = fileName.lastIndexOf(StringPool.PERIOD);
784 
785                 if (pos != -1) {
786                     extension = fileName.substring(pos);
787                     fileName = fileName.substring(0, pos);
788                 }
789             }
790 
791             File file = File.createTempFile(fileName, extension);
792 
793             os = new BufferedOutputStream(new FileOutputStream(file.getPath()));
794 
795             CalendarOutputter calOutput = new CalendarOutputter();
796 
797             calOutput.output(cal, os);
798 
799             return file;
800         }
801         catch (Exception e) {
802             _log.error(e, e);
803 
804             throw new SystemException(e);
805         }
806         finally {
807             ServletResponseUtil.cleanUp(os);
808         }
809     }
810 
811     protected Calendar getRecurrenceCal(
812         Calendar cal, Calendar tzICal, CalEvent event) {
813 
814         Calendar eventCal = CalendarFactoryUtil.getCalendar();
815         eventCal.setTime(event.getStartDate());
816 
817         Calendar recurrenceCal = (Calendar)tzICal.clone();
818         recurrenceCal.set(
819             Calendar.HOUR_OF_DAY, eventCal.get(Calendar.HOUR_OF_DAY));
820         recurrenceCal.set(
821             Calendar.MINUTE, eventCal.get(Calendar.MINUTE));
822         recurrenceCal.set(Calendar.SECOND, 0);
823         recurrenceCal.set(Calendar.MILLISECOND, 0);
824 
825         if (event.isTimeZoneSensitive()) {
826             int gmtDate = eventCal.get(Calendar.DATE);
827             long gmtMills = eventCal.getTimeInMillis();
828 
829             eventCal.setTimeZone(cal.getTimeZone());
830 
831             int tziDate = eventCal.get(Calendar.DATE);
832             long tziMills = Time.getDate(eventCal).getTime();
833 
834             if (gmtDate != tziDate) {
835                 int diffDate = 0;
836 
837                 if (gmtMills > tziMills) {
838                     diffDate = (int)Math.ceil(
839                         (double)(gmtMills - tziMills) / Time.DAY);
840                 }
841                 else {
842                     diffDate = (int)Math.floor(
843                         (double)(gmtMills - tziMills) / Time.DAY);
844                 }
845 
846                 recurrenceCal.add(Calendar.DATE, diffDate);
847             }
848         }
849 
850         return recurrenceCal;
851     }
852 
853     protected void importICal4j(
854             long userId, long plid, VEvent event)
855         throws PortalException, SystemException {
856 
857         User user = userPersistence.findByPrimaryKey(userId);
858 
859         TimeZone timeZone = user.getTimeZone();
860 
861         // X iCal property
862 
863         Property timeZoneXProperty = event.getProperty(
864             TimeZoneSensitive.PROPERTY_NAME);
865 
866         boolean timeZoneXPropertyValue = true;
867 
868         if (Validator.isNotNull(timeZoneXProperty) &&
869             timeZoneXProperty.getValue().equals("FALSE")) {
870 
871             timeZoneXPropertyValue = false;
872         }
873 
874         // Title
875 
876         String title = StringPool.BLANK;
877 
878         if (event.getSummary() != null) {
879             title = event.getSummary().getValue();
880         }
881 
882         // Description
883 
884         String description = StringPool.BLANK;
885 
886         if (event.getDescription() != null) {
887             description = event.getDescription().getValue();
888         }
889 
890         // Start date
891 
892         DtStart dtStart = event.getStartDate();
893 
894         Calendar startDate = toCalendar(
895             dtStart, timeZone, timeZoneXPropertyValue);
896 
897         startDate.setTime(dtStart.getDate());
898 
899         // End date
900 
901         Calendar endDate = null;
902 
903         DtEnd dtEnd = event.getEndDate(true);
904 
905         RRule rrule = (RRule)event.getProperty(Property.RRULE);
906 
907         if (Validator.isNotNull(dtEnd)) {
908             endDate = toCalendar(dtEnd, timeZone, timeZoneXPropertyValue);
909 
910             endDate.setTime(dtEnd.getDate());
911         }
912         else {
913             endDate = (Calendar)startDate.clone();
914             endDate.add(Calendar.DATE, 1);
915         }
916 
917         // Duration
918 
919         long diffMillis = 0;
920         long durationHours = 24;
921         long durationMins = 0;
922         boolean multiDayEvent = false;
923 
924         if (Validator.isNotNull(dtEnd)) {
925             diffMillis =
926                 dtEnd.getDate().getTime() - startDate.getTimeInMillis();
927             durationHours = diffMillis / Time.HOUR;
928             durationMins = (diffMillis / Time.MINUTE) - (durationHours * 60);
929 
930             if ((durationHours > 24) ||
931                 ((durationHours == 24) && (durationMins > 0))) {
932 
933                 durationHours = 24;
934                 durationMins = 0;
935                 multiDayEvent = true;
936             }
937         }
938 
939         // All day
940 
941         boolean allDay = false;
942 
943         if (isICal4jDateOnly(event.getStartDate()) || multiDayEvent) {
944             allDay = true;
945         }
946 
947         // Time zone sensitive
948 
949         boolean timeZoneSensitive = true;
950 
951         if (allDay || !timeZoneXPropertyValue) {
952             timeZoneSensitive = false;
953         }
954 
955         // Type
956 
957         String type = StringPool.BLANK;
958 
959         Property comment = event.getProperty(Property.COMMENT);
960 
961         if (Validator.isNotNull(comment) &&
962             ArrayUtil.contains(CalEventImpl.TYPES, comment.getValue())) {
963 
964             type = comment.getValue();
965         }
966 
967         // Recurrence
968 
969         boolean repeating = false;
970         TZSRecurrence recurrence = null;
971 
972         if (multiDayEvent) {
973             repeating = true;
974 
975             Calendar recStartCal = CalendarFactoryUtil.getCalendar(timeZone);
976 
977             recStartCal.setTime(startDate.getTime());
978 
979             com.liferay.portal.kernel.cal.Duration duration =
980                 new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0);
981 
982             recurrence = new TZSRecurrence(
983                 recStartCal, duration, Recurrence.DAILY);
984 
985             Calendar until = (Calendar) startDate.clone();
986 
987             until.setTimeInMillis(until.getTimeInMillis() + diffMillis);
988 
989             recurrence.setUntil(until);
990 
991             endDate = recurrence.getUntil();
992         }
993         else if (rrule != null) {
994             repeating = true;
995             recurrence = toRecurrence(rrule, timeZone, startDate);
996 
997             if (recurrence.getUntil() != null) {
998                 endDate = recurrence.getUntil();
999             }
1000        }
1001
1002        // Reminder
1003
1004        String remindBy = "none";
1005        int firstReminder = 300000;
1006        int secondReminder = 300000;
1007
1008        // Permissions
1009
1010        boolean addCommunityPermissions = false;
1011        boolean addGuestPermissions = false;
1012
1013        addEvent(
1014            userId, plid, title, description, startDate.get(Calendar.MONTH),
1015            startDate.get(Calendar.DAY_OF_MONTH), startDate.get(Calendar.YEAR),
1016            startDate.get(Calendar.HOUR_OF_DAY),
1017            startDate.get(Calendar.MINUTE), endDate.get(Calendar.MONTH),
1018            endDate.get(Calendar.DAY_OF_MONTH), endDate.get(Calendar.YEAR),
1019            (int)durationHours, (int)durationMins, allDay,
1020            timeZoneSensitive, type, repeating, recurrence, remindBy,
1021            firstReminder, secondReminder, addCommunityPermissions,
1022            addGuestPermissions);
1023
1024    }
1025
1026    protected boolean isICal4jDateOnly(DateProperty date) {
1027        if (Validator.isNotNull(date.getParameter(Parameter.VALUE)) &&
1028            date.getParameter(Parameter.VALUE).getValue().equals("DATE")) {
1029
1030            return true;
1031        }
1032
1033        return false;
1034    }
1035
1036    protected void remindUser(CalEvent event, User user) {
1037        String remindBy = event.getRemindBy();
1038
1039        if (remindBy.equals(CalEventImpl.REMIND_BY_NONE)) {
1040            return;
1041        }
1042
1043        try {
1044            long ownerId = event.getGroupId();
1045            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1046            long plid = PortletKeys.PREFS_PLID_SHARED;
1047            String portletId = PortletKeys.CALENDAR;
1048
1049            PortletPreferences prefs =
1050                portletPreferencesLocalService.getPreferences(
1051                    event.getCompanyId(), ownerId, ownerType, plid, portletId);
1052
1053            Company company = companyPersistence.findByPrimaryKey(
1054                user.getCompanyId());
1055
1056            Contact contact = user.getContact();
1057
1058            String portletName = PortalUtil.getPortletTitle(
1059                PortletKeys.CALENDAR, user);
1060
1061            String fromName = CalUtil.getEmailFromName(prefs);
1062            String fromAddress = CalUtil.getEmailFromAddress(prefs);
1063
1064            String toName = user.getFullName();
1065            String toAddress = user.getEmailAddress();
1066
1067            if (remindBy.equals(CalEventImpl.REMIND_BY_SMS)) {
1068                toAddress = contact.getSmsSn();
1069            }
1070
1071            String subject = CalUtil.getEmailEventReminderSubject(prefs);
1072            String body = CalUtil.getEmailEventReminderBody(prefs);
1073
1074            DateFormat dateFormatDateTime = DateFormats.getDateTime(
1075                user.getLocale(), user.getTimeZone());
1076
1077            subject = StringUtil.replace(
1078                subject,
1079                new String[] {
1080                    "[$EVENT_START_DATE$]",
1081                    "[$EVENT_TITLE$]",
1082                    "[$FROM_ADDRESS$]",
1083                    "[$FROM_NAME$]",
1084                    "[$PORTAL_URL$]",
1085                    "[$PORTLET_NAME$]",
1086                    "[$TO_ADDRESS$]",
1087                    "[$TO_NAME$]"
1088                },
1089                new String[] {
1090                    dateFormatDateTime.format(event.getStartDate()),
1091                    event.getTitle(),
1092                    fromAddress,
1093                    fromName,
1094                    company.getVirtualHost(),
1095                    portletName,
1096                    toAddress,
1097                    toName,
1098                });
1099
1100            body = StringUtil.replace(
1101                body,
1102                new String[] {
1103                    "[$EVENT_START_DATE$]",
1104                    "[$EVENT_TITLE$]",
1105                    "[$FROM_ADDRESS$]",
1106                    "[$FROM_NAME$]",
1107                    "[$PORTAL_URL$]",
1108                    "[$PORTLET_NAME$]",
1109                    "[$TO_ADDRESS$]",
1110                    "[$TO_NAME$]"
1111                },
1112                new String[] {
1113                    dateFormatDateTime.format(event.getStartDate()),
1114                    event.getTitle(),
1115                    fromAddress,
1116                    fromName,
1117                    company.getVirtualHost(),
1118                    portletName,
1119                    toAddress,
1120                    toName,
1121                });
1122
1123            if (remindBy.equals(CalEventImpl.REMIND_BY_EMAIL) ||
1124                remindBy.equals(CalEventImpl.REMIND_BY_SMS)) {
1125
1126                InternetAddress from = new InternetAddress(
1127                    fromAddress, fromName);
1128
1129                InternetAddress to = new InternetAddress(toAddress, toName);
1130
1131                MailMessage message = new MailMessage(
1132                    from, to, subject, body, true);
1133
1134                mailService.sendEmail(message);
1135            }
1136            else if (remindBy.equals(CalEventImpl.REMIND_BY_AIM) &&
1137                     Validator.isNotNull(contact.getAimSn())) {
1138
1139                AIMConnector.send(contact.getAimSn(), body);
1140            }
1141            else if (remindBy.equals(CalEventImpl.REMIND_BY_ICQ) &&
1142                     Validator.isNotNull(contact.getIcqSn())) {
1143
1144                ICQConnector.send(contact.getIcqSn(), body);
1145            }
1146            else if (remindBy.equals(CalEventImpl.REMIND_BY_MSN) &&
1147                     Validator.isNotNull(contact.getMsnSn())) {
1148
1149                MSNConnector.send(contact.getMsnSn(), body);
1150            }
1151            else if (remindBy.equals(CalEventImpl.REMIND_BY_YM) &&
1152                     Validator.isNotNull(contact.getYmSn())) {
1153
1154                YMConnector.send(contact.getYmSn(), body);
1155            }
1156        }
1157        catch (Exception e) {
1158            _log.error(e);
1159        }
1160    }
1161
1162    protected void remindUser(
1163        CalEvent event, User user, Calendar startDate, Calendar now) {
1164
1165        long diff =
1166            (startDate.getTime().getTime() - now.getTime().getTime()) /
1167            CheckEventJob.INTERVAL;
1168
1169        if ((diff == (event.getFirstReminder() / CheckEventJob.INTERVAL)) ||
1170            (diff ==
1171                (event.getSecondReminder() / CheckEventJob.INTERVAL))) {
1172
1173            remindUser(event, user);
1174        }
1175    }
1176
1177    protected Calendar toCalendar(
1178        DateProperty date, TimeZone timeZone, boolean timeZoneSensitive) {
1179
1180        Calendar cal = null;
1181
1182        if (isICal4jDateOnly(date)) {
1183            cal = Calendar.getInstance();
1184        }
1185        else if (!timeZoneSensitive) {
1186            cal = Calendar.getInstance(TimeZone.getTimeZone(StringPool.UTC));
1187        }
1188        else {
1189            cal = Calendar.getInstance(timeZone);
1190        }
1191
1192        return cal;
1193    }
1194
1195    protected int toCalendarWeekDay(WeekDay weekDay) {
1196        int dayOfWeeek = 0;
1197
1198        if (weekDay.getDay().equals(WeekDay.SU.getDay())) {
1199            dayOfWeeek = Calendar.SUNDAY;
1200        }
1201        else if (weekDay.getDay().equals(WeekDay.MO.getDay())) {
1202            dayOfWeeek = Calendar.MONDAY;
1203        }
1204        else if (weekDay.getDay().equals(WeekDay.TU.getDay())) {
1205            dayOfWeeek = Calendar.TUESDAY;
1206        }
1207        else if (weekDay.getDay().equals(WeekDay.WE.getDay())) {
1208            dayOfWeeek = Calendar.WEDNESDAY;
1209        }
1210        else if (weekDay.getDay().equals(WeekDay.TH.getDay())) {
1211            dayOfWeeek = Calendar.THURSDAY;
1212        }
1213        else if (weekDay.getDay().equals(WeekDay.FR.getDay())) {
1214            dayOfWeeek = Calendar.FRIDAY;
1215        }
1216        else if (weekDay.getDay().equals(WeekDay.SA.getDay())) {
1217            dayOfWeeek = Calendar.SATURDAY;
1218        }
1219
1220        return dayOfWeeek;
1221    }
1222
1223    protected net.fortuna.ical4j.model.Calendar toICalCalendar(
1224        long userId, List<CalEvent> events)
1225        throws PortalException, SystemException {
1226
1227        net.fortuna.ical4j.model.Calendar iCal =
1228            new net.fortuna.ical4j.model.Calendar();
1229
1230        ProdId prodId = new ProdId(
1231            "-//Liferay Inc//Liferay Portal " + ReleaseInfo.getVersion() +
1232            "//EN");
1233
1234        PropertyList props = iCal.getProperties();
1235
1236        props.add(prodId);
1237        props.add(Version.VERSION_2_0);
1238        props.add(CalScale.GREGORIAN);
1239
1240        User user = userPersistence.findByPrimaryKey(userId);
1241        TimeZone timeZone = user.getTimeZone();
1242
1243        List<VEvent> components = iCal.getComponents();
1244
1245        Iterator<CalEvent> itr = events.iterator();
1246
1247        while (itr.hasNext()) {
1248            CalEvent event = itr.next();
1249
1250            components.add(toICalVEvent(event, timeZone));
1251        }
1252
1253        return iCal;
1254    }
1255
1256    protected Recur toICalRecurrence(TZSRecurrence recurrence) {
1257        Recur recur = null;
1258
1259        int recurrenceType = recurrence.getFrequency();
1260
1261        int interval = recurrence.getInterval();
1262
1263        if (recurrenceType == Recurrence.DAILY) {
1264            recur = new Recur(Recur.DAILY, -1);
1265
1266            if (interval >= 1) {
1267                recur.setInterval(interval);
1268            }
1269
1270            DayAndPosition[] byDay = recurrence.getByDay();
1271
1272            if (byDay != null) {
1273                for (int i = 0; i < byDay.length; i++) {
1274                    WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1275
1276                    recur.getDayList().add(weekDay);
1277                }
1278            }
1279
1280        }
1281        else if (recurrenceType == Recurrence.WEEKLY) {
1282            recur = new Recur(Recur.WEEKLY, -1);
1283
1284            recur.setInterval(interval);
1285
1286            DayAndPosition[] byDay = recurrence.getByDay();
1287
1288            if (byDay != null) {
1289                for (int i = 0; i < byDay.length; i++) {
1290                    WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1291
1292                    recur.getDayList().add(weekDay);
1293                }
1294            }
1295        }
1296        else if (recurrenceType == Recurrence.MONTHLY) {
1297            recur = new Recur(Recur.MONTHLY, -1);
1298
1299            recur.setInterval(interval);
1300
1301            int[] byMonthDay = recurrence.getByMonthDay();
1302
1303            if (byMonthDay != null) {
1304                Integer monthDay = new Integer(byMonthDay[0]);
1305
1306                recur.getMonthDayList().add(monthDay);
1307            }
1308            else if (recurrence.getByDay() != null){
1309                DayAndPosition[] byDay = recurrence.getByDay();
1310
1311                WeekDay weekDay = toICalWeekDay(byDay[0].getDayOfWeek());
1312
1313                recur.getDayList().add(weekDay);
1314
1315                Integer position = new Integer(byDay[0].getDayPosition());
1316
1317                recur.getSetPosList().add(position);
1318            }
1319        }
1320        else if (recurrenceType == Recurrence.YEARLY) {
1321            recur = new Recur(Recur.YEARLY, -1);
1322
1323            recur.setInterval(interval);
1324        }
1325
1326        Calendar until = recurrence.getUntil();
1327
1328        if (until != null) {
1329            DateTime dateTime = new DateTime(until.getTime());
1330
1331            recur.setUntil(dateTime);
1332        }
1333
1334        return recur;
1335    }
1336
1337    protected VEvent toICalVEvent(CalEvent event, TimeZone timeZone){
1338        VEvent vEvent = new VEvent();
1339
1340        PropertyList eventProps = vEvent.getProperties();
1341
1342        // UID
1343
1344        Uid uid = new Uid(PortalUUIDUtil.generate());
1345
1346        eventProps.add(uid);
1347
1348        if (event.isAllDay()) {
1349
1350            // Start date
1351
1352            DtStart dtStart = new DtStart(
1353                new net.fortuna.ical4j.model.Date(event.getStartDate()));
1354
1355            eventProps.add(dtStart);
1356
1357            Property dtStartProperty = eventProps.getProperty(Property.DTSTART);
1358
1359            dtStartProperty.getParameters().add(Value.DATE);
1360        }
1361        else {
1362
1363            // Start date
1364
1365            DtStart dtStart = new DtStart(new DateTime(event.getStartDate()));
1366
1367            eventProps.add(dtStart);
1368
1369            // Duration
1370
1371            Duration duration = new Duration(
1372                new Dur(
1373                    0, event.getDurationHour(), event.getDurationMinute(), 0));
1374
1375            eventProps.add(duration);
1376        }
1377
1378        // Summary
1379
1380        Summary summary = new Summary(event.getTitle());
1381
1382        eventProps.add(summary);
1383
1384        // Description
1385
1386        Description description = new Description(event.getDescription());
1387
1388        eventProps.add(description);
1389
1390        // Comment
1391
1392        Comment comment = new Comment(event.getType());
1393
1394        eventProps.add(comment);
1395
1396        // Recurrence rule
1397
1398        if (event.isRepeating()) {
1399            Recur recur = toICalRecurrence(event.getRecurrenceObj());
1400
1401            RRule rRule = new RRule(recur);
1402
1403            eventProps.add(rRule);
1404        }
1405
1406        // Time zone sensitive
1407
1408        if (!event.getTimeZoneSensitive()) {
1409            eventProps.add(new TimeZoneSensitive("FALSE"));
1410        }
1411
1412        return vEvent;
1413    }
1414
1415    protected WeekDay toICalWeekDay(int dayOfWeek) {
1416        WeekDay weekDay = null;
1417
1418        if (dayOfWeek == Calendar.SUNDAY) {
1419            weekDay = WeekDay.SU;
1420        }
1421        else if (dayOfWeek == Calendar.MONDAY) {
1422            weekDay = WeekDay.MO;
1423        }
1424        else if (dayOfWeek == Calendar.TUESDAY) {
1425            weekDay = WeekDay.TU;
1426        }
1427        else if (dayOfWeek == Calendar.WEDNESDAY) {
1428            weekDay = WeekDay.WE;
1429        }
1430        else if (dayOfWeek == Calendar.THURSDAY) {
1431            weekDay = WeekDay.TH;
1432        }
1433        else if (dayOfWeek == Calendar.FRIDAY) {
1434            weekDay = WeekDay.FR;
1435        }
1436        else if (dayOfWeek == Calendar.SATURDAY) {
1437            weekDay = WeekDay.SA;
1438        }
1439
1440        return weekDay;
1441    }
1442
1443    protected TZSRecurrence toRecurrence(
1444        RRule rRule, TimeZone timeZone, Calendar startDate) {
1445
1446        Recur recur = rRule.getRecur();
1447
1448        Calendar recStartCal = CalendarFactoryUtil.getCalendar(timeZone);
1449
1450        recStartCal.setTime(startDate.getTime());
1451
1452        TZSRecurrence recurrence = new TZSRecurrence(
1453            recStartCal,
1454            new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0));
1455
1456        recurrence.setWeekStart(Calendar.SUNDAY);
1457
1458        if (recur.getInterval() > 1){
1459            recurrence.setInterval(recur.getInterval());
1460        }
1461
1462        Calendar until = Calendar.getInstance(timeZone);
1463
1464        String frequency = recur.getFrequency();
1465
1466        if (Validator.isNotNull(recur.getUntil())) {
1467            until.setTime(recur.getUntil());
1468
1469            recurrence.setUntil(until);
1470        }
1471        else if (rRule.getValue().indexOf("COUNT") >= 0) {
1472            until.setTimeInMillis(startDate.getTimeInMillis());
1473
1474            int addField = 0;
1475
1476            if (Recur.DAILY.equals(frequency)) {
1477                addField = Calendar.DAY_OF_YEAR;
1478            }
1479            else if (Recur.WEEKLY.equals(frequency)) {
1480                addField = Calendar.WEEK_OF_YEAR;
1481            }
1482            else if (Recur.MONTHLY.equals(frequency)) {
1483                addField = Calendar.MONTH;
1484            }
1485            else if (Recur.YEARLY.equals(frequency)) {
1486                addField = Calendar.YEAR;
1487            }
1488
1489            int addAmount = recurrence.getInterval() * recur.getCount();
1490
1491            until.add(addField, addAmount);
1492            until.add(Calendar.DAY_OF_YEAR, -1);
1493
1494            recurrence.setUntil(until);
1495        }
1496
1497        if (Recur.DAILY.equals(frequency)) {
1498            recurrence.setFrequency(Recurrence.DAILY);
1499
1500            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1501
1502            Iterator<WeekDay> itr = recur.getDayList().iterator();
1503
1504            while (itr.hasNext()) {
1505                WeekDay weekDay = itr.next();
1506
1507                dayPosList.add(
1508                    new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1509            }
1510
1511            if (!dayPosList.isEmpty()) {
1512                recurrence.setByDay(
1513                    dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1514            }
1515        }
1516        else if (Recur.WEEKLY.equals(frequency)) {
1517            recurrence.setFrequency(Recurrence.WEEKLY);
1518
1519            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1520
1521            Iterator<WeekDay> itr = recur.getDayList().iterator();
1522
1523            while (itr.hasNext()) {
1524                WeekDay weekDay = itr.next();
1525
1526                dayPosList.add(
1527                    new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1528            }
1529
1530            if (!dayPosList.isEmpty()) {
1531                recurrence.setByDay(
1532                    dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1533            }
1534        }
1535        else if (Recur.MONTHLY.equals(frequency)) {
1536            recurrence.setFrequency(Recurrence.MONTHLY);
1537
1538            Iterator<Integer> monthDayListItr =
1539                recur.getMonthDayList().iterator();
1540
1541            if (monthDayListItr.hasNext()) {
1542                Integer monthDay = monthDayListItr.next();
1543
1544                recurrence.setByMonthDay(new int[] {monthDay.intValue()});
1545            }
1546
1547            Iterator<WeekDay> dayListItr = recur.getDayList().iterator();
1548
1549            if (dayListItr.hasNext()) {
1550                WeekDay weekDay = dayListItr.next();
1551
1552                DayAndPosition[] dayPos = {
1553                    new DayAndPosition(toCalendarWeekDay(weekDay),
1554                    weekDay.getOffset())
1555                };
1556
1557                recurrence.setByDay(dayPos);
1558            }
1559        }
1560        else if (Recur.YEARLY.equals(frequency)) {
1561            recurrence.setFrequency(Recurrence.YEARLY);
1562        }
1563
1564        return recurrence;
1565    }
1566
1567    protected void validate(
1568            String title, int startDateMonth, int startDateDay,
1569            int startDateYear, int endDateMonth, int endDateDay,
1570            int endDateYear, int durationHour, int durationMinute,
1571            boolean allDay)
1572        throws PortalException {
1573
1574        if (Validator.isNull(title)) {
1575            throw new EventTitleException();
1576        }
1577        else if (!Validator.isDate(
1578                startDateMonth, startDateDay, startDateYear)) {
1579
1580            throw new EventStartDateException();
1581        }
1582        else if (!Validator.isDate(endDateMonth, endDateDay, endDateYear)) {
1583            throw new EventEndDateException();
1584        }
1585
1586        if (!allDay && durationHour <= 0 && durationMinute <= 0) {
1587            throw new EventDurationException();
1588        }
1589
1590        Calendar startDate = CalendarFactoryUtil.getCalendar(
1591            startDateYear, startDateMonth, startDateDay);
1592
1593        Calendar endDate = CalendarFactoryUtil.getCalendar(
1594            endDateYear, endDateMonth, endDateDay);
1595
1596        if (startDate.after(endDate)) {
1597            throw new EventEndDateException();
1598        }
1599    }
1600
1601    private static Log _log = LogFactory.getLog(CalEventLocalServiceImpl.class);
1602
1603}