1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portlet.calendar.service.impl;
21  
22  import com.liferay.portal.PortalException;
23  import com.liferay.portal.SystemException;
24  import com.liferay.portal.im.AIMConnector;
25  import com.liferay.portal.im.ICQConnector;
26  import com.liferay.portal.im.MSNConnector;
27  import com.liferay.portal.im.YMConnector;
28  import com.liferay.portal.kernel.cal.DayAndPosition;
29  import com.liferay.portal.kernel.cal.Recurrence;
30  import com.liferay.portal.kernel.cal.TZSRecurrence;
31  import com.liferay.portal.kernel.log.Log;
32  import com.liferay.portal.kernel.log.LogFactoryUtil;
33  import com.liferay.portal.kernel.mail.MailMessage;
34  import com.liferay.portal.kernel.util.ArrayUtil;
35  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
36  import com.liferay.portal.kernel.util.CalendarUtil;
37  import com.liferay.portal.kernel.util.DateFormats;
38  import com.liferay.portal.kernel.util.LocaleUtil;
39  import com.liferay.portal.kernel.util.ReleaseInfo;
40  import com.liferay.portal.kernel.util.StringPool;
41  import com.liferay.portal.kernel.util.StringUtil;
42  import com.liferay.portal.kernel.util.Time;
43  import com.liferay.portal.kernel.util.TimeZoneUtil;
44  import com.liferay.portal.kernel.util.UnmodifiableList;
45  import com.liferay.portal.kernel.util.Validator;
46  import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
47  import com.liferay.portal.model.Company;
48  import com.liferay.portal.model.Contact;
49  import com.liferay.portal.model.ModelHintsUtil;
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 /**
116  * <a href="CalEventLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
117  *
118  * @author Brian Wing Shun Chan
119  * @author Bruno Farache
120  * @author Samuel Kong
121  * @author Ganesh Ram
122  *
123  */
124 public class CalEventLocalServiceImpl extends CalEventLocalServiceBaseImpl {
125 
126     public CalEvent addEvent(
127             long userId, long plid, String title, String description,
128             int startDateMonth, int startDateDay, int startDateYear,
129             int startDateHour, int startDateMinute, int endDateMonth,
130             int endDateDay, int endDateYear, int durationHour,
131             int durationMinute, boolean allDay, boolean timeZoneSensitive,
132             String type, boolean repeating, TZSRecurrence recurrence,
133             int remindBy, int firstReminder, int secondReminder,
134             boolean addCommunityPermissions, boolean addGuestPermissions)
135         throws PortalException, SystemException {
136 
137         return addEvent(
138             null, userId, plid, title, description, startDateMonth,
139             startDateDay, startDateYear, startDateHour, startDateMinute,
140             endDateMonth, endDateDay, endDateYear, durationHour, durationMinute,
141             allDay, timeZoneSensitive, type, repeating, recurrence, remindBy,
142             firstReminder, secondReminder,
143             Boolean.valueOf(addCommunityPermissions),
144             Boolean.valueOf(addGuestPermissions), null, null);
145     }
146 
147     public CalEvent addEvent(
148             String uuid, long userId, long plid, String title,
149             String description, int startDateMonth, int startDateDay,
150             int startDateYear, int startDateHour, int startDateMinute,
151             int endDateMonth, int endDateDay, int endDateYear, int durationHour,
152             int durationMinute, boolean allDay, boolean timeZoneSensitive,
153             String type, boolean repeating, TZSRecurrence recurrence,
154             int remindBy, int firstReminder, int secondReminder,
155             boolean addCommunityPermissions, boolean addGuestPermissions)
156         throws PortalException, SystemException {
157 
158         return addEvent(
159             uuid, userId, plid, title, description, startDateMonth,
160             startDateDay, startDateYear, startDateHour, startDateMinute,
161             endDateMonth, endDateDay, endDateYear, durationHour, durationMinute,
162             allDay, timeZoneSensitive, type, repeating, recurrence, remindBy,
163             firstReminder, secondReminder, new Boolean(addCommunityPermissions),
164             new Boolean(addGuestPermissions), null, null);
165     }
166 
167     public CalEvent addEvent(
168             long userId, long plid, String title, String description,
169             int startDateMonth, int startDateDay, int startDateYear,
170             int startDateHour, int startDateMinute, int endDateMonth,
171             int endDateDay, int endDateYear, int durationHour,
172             int durationMinute, boolean allDay, boolean timeZoneSensitive,
173             String type, boolean repeating, TZSRecurrence recurrence,
174             int remindBy, int firstReminder, int secondReminder,
175             String[] communityPermissions, String[] guestPermissions)
176         throws PortalException, SystemException {
177 
178         return addEvent(
179             null, userId, plid, title, description, startDateMonth,
180             startDateDay, startDateYear, startDateHour, startDateMinute,
181             endDateMonth, endDateDay, endDateYear, durationHour, durationMinute,
182             allDay, timeZoneSensitive, type, repeating, recurrence, remindBy,
183             firstReminder, secondReminder, null, null, communityPermissions,
184             guestPermissions);
185     }
186 
187     public CalEvent addEvent(
188             String uuid, long userId, long plid, String title,
189             String description, int startDateMonth, int startDateDay,
190             int startDateYear, int startDateHour, int startDateMinute,
191             int endDateMonth, int endDateDay, int endDateYear, int durationHour,
192             int durationMinute, boolean allDay, boolean timeZoneSensitive,
193             String type, boolean repeating, TZSRecurrence recurrence,
194             int remindBy, int firstReminder, int secondReminder,
195             Boolean addCommunityPermissions, Boolean addGuestPermissions,
196             String[] communityPermissions, String[] guestPermissions)
197         throws PortalException, SystemException {
198 
199         // Event
200 
201         User user = userPersistence.findByPrimaryKey(userId);
202         long groupId = PortalUtil.getScopeGroupId(plid);
203         Date now = new Date();
204 
205         Locale locale = null;
206         TimeZone timeZone = null;
207 
208         if (timeZoneSensitive) {
209             locale = user.getLocale();
210             timeZone = user.getTimeZone();
211         }
212         else {
213             locale = LocaleUtil.getDefault();
214             timeZone = TimeZoneUtil.getDefault();
215         }
216 
217         Calendar startDate = CalendarFactoryUtil.getCalendar(timeZone, locale);
218 
219         startDate.set(Calendar.MONTH, startDateMonth);
220         startDate.set(Calendar.DATE, startDateDay);
221         startDate.set(Calendar.YEAR, startDateYear);
222         startDate.set(Calendar.HOUR_OF_DAY, startDateHour);
223         startDate.set(Calendar.MINUTE, startDateMinute);
224         startDate.set(Calendar.SECOND, 0);
225         startDate.set(Calendar.MILLISECOND, 0);
226 
227         Calendar endDate = CalendarFactoryUtil.getCalendar(timeZone, locale);
228 
229         endDate.set(Calendar.MONTH, endDateMonth);
230         endDate.set(Calendar.DATE, endDateDay);
231         endDate.set(Calendar.YEAR, endDateYear);
232         endDate.set(Calendar.HOUR_OF_DAY, 23);
233         endDate.set(Calendar.MINUTE, 59);
234         endDate.set(Calendar.SECOND, 59);
235         endDate.set(Calendar.MILLISECOND, 999);
236 
237         if (allDay) {
238             startDate.set(Calendar.HOUR_OF_DAY, 0);
239             startDate.set(Calendar.MINUTE, 0);
240 
241             durationHour = 24;
242             durationMinute = 0;
243         }
244 
245         validate(
246             title, startDateMonth, startDateDay, startDateYear, endDateMonth,
247             endDateDay, endDateYear, durationHour, durationMinute, allDay,
248             repeating);
249 
250         long eventId = counterLocalService.increment();
251 
252         CalEvent event = calEventPersistence.create(eventId);
253 
254         event.setUuid(uuid);
255         event.setGroupId(groupId);
256         event.setCompanyId(user.getCompanyId());
257         event.setUserId(user.getUserId());
258         event.setUserName(user.getFullName());
259         event.setCreateDate(now);
260         event.setModifiedDate(now);
261         event.setTitle(title);
262         event.setDescription(description);
263         event.setStartDate(startDate.getTime());
264         event.setEndDate(endDate.getTime());
265         event.setDurationHour(durationHour);
266         event.setDurationMinute(durationMinute);
267         event.setAllDay(allDay);
268         event.setTimeZoneSensitive(timeZoneSensitive);
269         event.setType(type);
270         event.setRepeating(repeating);
271         event.setRecurrenceObj(recurrence);
272         event.setRemindBy(remindBy);
273         event.setFirstReminder(firstReminder);
274         event.setSecondReminder(secondReminder);
275 
276         calEventPersistence.update(event, false);
277 
278         // Resources
279 
280         if ((addCommunityPermissions != null) &&
281             (addGuestPermissions != null)) {
282 
283             addEventResources(
284                 event, addCommunityPermissions.booleanValue(),
285                 addGuestPermissions.booleanValue());
286         }
287         else {
288             addEventResources(event, communityPermissions, guestPermissions);
289         }
290 
291         // Social
292 
293         socialActivityLocalService.addActivity(
294             userId, groupId, CalEvent.class.getName(), eventId,
295             CalendarActivityKeys.ADD_EVENT, StringPool.BLANK, 0);
296 
297         // Pool
298 
299         CalEventLocalUtil.clearEventsPool(event.getGroupId());
300 
301         return event;
302     }
303 
304     public void addEventResources(
305             long eventId, boolean addCommunityPermissions,
306             boolean addGuestPermissions)
307         throws PortalException, SystemException {
308 
309         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
310 
311         addEventResources(
312             event, addCommunityPermissions, addGuestPermissions);
313     }
314 
315     public void addEventResources(
316             CalEvent event, boolean addCommunityPermissions,
317             boolean addGuestPermissions)
318         throws PortalException, SystemException {
319 
320         resourceLocalService.addResources(
321             event.getCompanyId(), event.getGroupId(), event.getUserId(),
322             CalEvent.class.getName(), event.getEventId(), false,
323             addCommunityPermissions, addGuestPermissions);
324     }
325 
326     public void addEventResources(
327             long eventId, String[] communityPermissions,
328             String[] guestPermissions)
329         throws PortalException, SystemException {
330 
331         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
332 
333         addEventResources(event, communityPermissions, guestPermissions);
334     }
335 
336     public void addEventResources(
337             CalEvent event, String[] communityPermissions,
338             String[] guestPermissions)
339         throws PortalException, SystemException {
340 
341         resourceLocalService.addModelResources(
342             event.getCompanyId(), event.getGroupId(), event.getUserId(),
343             CalEvent.class.getName(), event.getEventId(), communityPermissions,
344             guestPermissions);
345     }
346 
347     public void checkEvents() throws PortalException, SystemException {
348         Iterator<CalEvent> itr = calEventPersistence.findByRemindBy(
349             CalEventImpl.REMIND_BY_NONE).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             int 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             repeating);
737 
738         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
739 
740         event.setModifiedDate(new Date());
741         event.setTitle(title);
742         event.setDescription(description);
743         event.setStartDate(startDate.getTime());
744         event.setEndDate(endDate.getTime());
745         event.setDurationHour(durationHour);
746         event.setDurationMinute(durationMinute);
747         event.setAllDay(allDay);
748         event.setTimeZoneSensitive(timeZoneSensitive);
749         event.setType(type);
750         event.setRepeating(repeating);
751         event.setRecurrenceObj(recurrence);
752         event.setRemindBy(remindBy);
753         event.setFirstReminder(firstReminder);
754         event.setSecondReminder(secondReminder);
755 
756         calEventPersistence.update(event, false);
757 
758         // Social
759 
760         socialActivityLocalService.addActivity(
761             userId, event.getGroupId(), CalEvent.class.getName(), eventId,
762             CalendarActivityKeys.UPDATE_EVENT, StringPool.BLANK, 0);
763 
764         // Pool
765 
766         CalEventLocalUtil.clearEventsPool(event.getGroupId());
767 
768         return event;
769     }
770 
771     protected File exportICal4j(
772             net.fortuna.ical4j.model.Calendar cal, String fileName)
773         throws SystemException {
774 
775         OutputStream os = null;
776 
777         try {
778             String extension = ".ics";
779 
780             if (Validator.isNull(fileName)) {
781                 fileName = "liferay.";
782             }
783             else {
784                 int pos = fileName.lastIndexOf(StringPool.PERIOD);
785 
786                 if (pos != -1) {
787                     extension = fileName.substring(pos);
788                     fileName = fileName.substring(0, pos);
789                 }
790             }
791 
792             File file = File.createTempFile(fileName, extension);
793 
794             os = new BufferedOutputStream(new FileOutputStream(file.getPath()));
795 
796             CalendarOutputter calOutput = new CalendarOutputter();
797 
798             if (cal.getComponents().isEmpty()) {
799                 calOutput.setValidating(false);
800             }
801 
802             calOutput.output(cal, os);
803 
804             return file;
805         }
806         catch (Exception e) {
807             _log.error(e, e);
808 
809             throw new SystemException(e);
810         }
811         finally {
812             ServletResponseUtil.cleanUp(os);
813         }
814     }
815 
816     protected Calendar getRecurrenceCal(
817         Calendar cal, Calendar tzICal, CalEvent event) {
818 
819         Calendar eventCal = CalendarFactoryUtil.getCalendar();
820         eventCal.setTime(event.getStartDate());
821 
822         Calendar recurrenceCal = (Calendar)tzICal.clone();
823         recurrenceCal.set(
824             Calendar.HOUR_OF_DAY, eventCal.get(Calendar.HOUR_OF_DAY));
825         recurrenceCal.set(
826             Calendar.MINUTE, eventCal.get(Calendar.MINUTE));
827         recurrenceCal.set(Calendar.SECOND, 0);
828         recurrenceCal.set(Calendar.MILLISECOND, 0);
829 
830         if (event.isTimeZoneSensitive()) {
831             int gmtDate = eventCal.get(Calendar.DATE);
832             long gmtMills = eventCal.getTimeInMillis();
833 
834             eventCal.setTimeZone(cal.getTimeZone());
835 
836             int tziDate = eventCal.get(Calendar.DATE);
837             long tziMills = Time.getDate(eventCal).getTime();
838 
839             if (gmtDate != tziDate) {
840                 int diffDate = 0;
841 
842                 if (gmtMills > tziMills) {
843                     diffDate = (int)Math.ceil(
844                         (double)(gmtMills - tziMills) / Time.DAY);
845                 }
846                 else {
847                     diffDate = (int)Math.floor(
848                         (double)(gmtMills - tziMills) / Time.DAY);
849                 }
850 
851                 recurrenceCal.add(Calendar.DATE, diffDate);
852             }
853         }
854 
855         return recurrenceCal;
856     }
857 
858     protected void importICal4j(
859             long userId, long plid, VEvent event)
860         throws PortalException, SystemException {
861 
862         User user = userPersistence.findByPrimaryKey(userId);
863 
864         TimeZone timeZone = user.getTimeZone();
865 
866         // X iCal property
867 
868         Property timeZoneXProperty = event.getProperty(
869             TimeZoneSensitive.PROPERTY_NAME);
870 
871         boolean timeZoneXPropertyValue = true;
872 
873         if (Validator.isNotNull(timeZoneXProperty) &&
874             timeZoneXProperty.getValue().equals("FALSE")) {
875 
876             timeZoneXPropertyValue = false;
877         }
878 
879         // Title
880 
881         String title = StringPool.BLANK;
882 
883         if (event.getSummary() != null) {
884             title = ModelHintsUtil.trimString(
885                 CalEvent.class.getName(), "title",
886                 event.getSummary().getValue());
887         }
888 
889         // Description
890 
891         String description = StringPool.BLANK;
892 
893         if (event.getDescription() != null) {
894             description = event.getDescription().getValue();
895         }
896 
897         // Start date
898 
899         DtStart dtStart = event.getStartDate();
900 
901         Calendar startDate = toCalendar(
902             dtStart, timeZone, timeZoneXPropertyValue);
903 
904         startDate.setTime(dtStart.getDate());
905 
906         // End date
907 
908         Calendar endDate = null;
909 
910         DtEnd dtEnd = event.getEndDate(true);
911 
912         RRule rrule = (RRule)event.getProperty(Property.RRULE);
913 
914         if (Validator.isNotNull(dtEnd)) {
915             endDate = toCalendar(dtEnd, timeZone, timeZoneXPropertyValue);
916 
917             endDate.setTime(dtEnd.getDate());
918         }
919         else {
920             endDate = (Calendar)startDate.clone();
921             endDate.add(Calendar.DATE, 1);
922         }
923 
924         // Duration
925 
926         long diffMillis = 0;
927         long durationHours = 24;
928         long durationMins = 0;
929         boolean multiDayEvent = false;
930 
931         if (Validator.isNotNull(dtEnd)) {
932             diffMillis =
933                 dtEnd.getDate().getTime() - startDate.getTimeInMillis();
934             durationHours = diffMillis / Time.HOUR;
935             durationMins = (diffMillis / Time.MINUTE) - (durationHours * 60);
936 
937             if ((durationHours > 24) ||
938                 ((durationHours == 24) && (durationMins > 0))) {
939 
940                 durationHours = 24;
941                 durationMins = 0;
942                 multiDayEvent = true;
943             }
944         }
945 
946         // All day
947 
948         boolean allDay = false;
949 
950         if (isICal4jDateOnly(event.getStartDate()) || multiDayEvent) {
951             allDay = true;
952         }
953 
954         // Time zone sensitive
955 
956         boolean timeZoneSensitive = true;
957 
958         if (allDay || !timeZoneXPropertyValue) {
959             timeZoneSensitive = false;
960         }
961 
962         // Type
963 
964         String type = StringPool.BLANK;
965 
966         Property comment = event.getProperty(Property.COMMENT);
967 
968         if (Validator.isNotNull(comment) &&
969             ArrayUtil.contains(CalEventImpl.TYPES, comment.getValue())) {
970 
971             type = comment.getValue();
972         }
973 
974         // Recurrence
975 
976         boolean repeating = false;
977         TZSRecurrence recurrence = null;
978 
979         if (multiDayEvent) {
980             repeating = true;
981 
982             Calendar recStartCal = CalendarFactoryUtil.getCalendar(timeZone);
983 
984             recStartCal.setTime(startDate.getTime());
985 
986             com.liferay.portal.kernel.cal.Duration duration =
987                 new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0);
988 
989             recurrence = new TZSRecurrence(
990                 recStartCal, duration, Recurrence.DAILY);
991 
992             Calendar until = (Calendar) startDate.clone();
993 
994             until.setTimeInMillis(until.getTimeInMillis() + diffMillis);
995 
996             recurrence.setUntil(until);
997 
998             endDate = recurrence.getUntil();
999         }
1000        else if (rrule != null) {
1001            repeating = true;
1002            recurrence = toRecurrence(rrule, timeZone, startDate);
1003
1004            if (recurrence.getUntil() != null) {
1005                endDate = recurrence.getUntil();
1006            }
1007        }
1008
1009        // Reminder
1010
1011        int remindBy = CalEventImpl.REMIND_BY_NONE;
1012        int firstReminder = 300000;
1013        int secondReminder = 300000;
1014
1015        // Permissions
1016
1017        boolean addCommunityPermissions = false;
1018        boolean addGuestPermissions = false;
1019
1020        addEvent(
1021            userId, plid, title, description, startDate.get(Calendar.MONTH),
1022            startDate.get(Calendar.DAY_OF_MONTH), startDate.get(Calendar.YEAR),
1023            startDate.get(Calendar.HOUR_OF_DAY),
1024            startDate.get(Calendar.MINUTE), endDate.get(Calendar.MONTH),
1025            endDate.get(Calendar.DAY_OF_MONTH), endDate.get(Calendar.YEAR),
1026            (int)durationHours, (int)durationMins, allDay,
1027            timeZoneSensitive, type, repeating, recurrence, remindBy,
1028            firstReminder, secondReminder, addCommunityPermissions,
1029            addGuestPermissions);
1030
1031    }
1032
1033    protected boolean isICal4jDateOnly(DateProperty date) {
1034        if (Validator.isNotNull(date.getParameter(Parameter.VALUE)) &&
1035            date.getParameter(Parameter.VALUE).getValue().equals("DATE")) {
1036
1037            return true;
1038        }
1039
1040        return false;
1041    }
1042
1043    protected void remindUser(CalEvent event, User user, Calendar startDate) {
1044        int remindBy = event.getRemindBy();
1045
1046        if (remindBy == CalEventImpl.REMIND_BY_NONE) {
1047            return;
1048        }
1049
1050        try {
1051            long ownerId = event.getGroupId();
1052            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1053            long plid = PortletKeys.PREFS_PLID_SHARED;
1054            String portletId = PortletKeys.CALENDAR;
1055
1056            PortletPreferences prefs =
1057                portletPreferencesLocalService.getPreferences(
1058                    event.getCompanyId(), ownerId, ownerType, plid, portletId);
1059
1060            Company company = companyPersistence.findByPrimaryKey(
1061                user.getCompanyId());
1062
1063            Contact contact = user.getContact();
1064
1065            String portletName = PortalUtil.getPortletTitle(
1066                PortletKeys.CALENDAR, user);
1067
1068            String fromName = CalUtil.getEmailFromName(prefs);
1069            String fromAddress = CalUtil.getEmailFromAddress(prefs);
1070
1071            String toName = user.getFullName();
1072            String toAddress = user.getEmailAddress();
1073
1074            if (remindBy == CalEventImpl.REMIND_BY_SMS) {
1075                toAddress = contact.getSmsSn();
1076            }
1077
1078            String subject = CalUtil.getEmailEventReminderSubject(prefs);
1079            String body = CalUtil.getEmailEventReminderBody(prefs);
1080
1081            DateFormat dateFormatDateTime = DateFormats.getDateTime(
1082                user.getLocale(), user.getTimeZone());
1083
1084            subject = StringUtil.replace(
1085                subject,
1086                new String[] {
1087                    "[$EVENT_START_DATE$]",
1088                    "[$EVENT_TITLE$]",
1089                    "[$FROM_ADDRESS$]",
1090                    "[$FROM_NAME$]",
1091                    "[$PORTAL_URL$]",
1092                    "[$PORTLET_NAME$]",
1093                    "[$TO_ADDRESS$]",
1094                    "[$TO_NAME$]"
1095                },
1096                new String[] {
1097                    dateFormatDateTime.format(startDate.getTime()),
1098                    event.getTitle(),
1099                    fromAddress,
1100                    fromName,
1101                    company.getVirtualHost(),
1102                    portletName,
1103                    toAddress,
1104                    toName,
1105                });
1106
1107            body = StringUtil.replace(
1108                body,
1109                new String[] {
1110                    "[$EVENT_START_DATE$]",
1111                    "[$EVENT_TITLE$]",
1112                    "[$FROM_ADDRESS$]",
1113                    "[$FROM_NAME$]",
1114                    "[$PORTAL_URL$]",
1115                    "[$PORTLET_NAME$]",
1116                    "[$TO_ADDRESS$]",
1117                    "[$TO_NAME$]"
1118                },
1119                new String[] {
1120                    dateFormatDateTime.format(startDate.getTime()),
1121                    event.getTitle(),
1122                    fromAddress,
1123                    fromName,
1124                    company.getVirtualHost(),
1125                    portletName,
1126                    toAddress,
1127                    toName,
1128                });
1129
1130            if ((remindBy == CalEventImpl.REMIND_BY_EMAIL) ||
1131                (remindBy == CalEventImpl.REMIND_BY_SMS)) {
1132
1133                InternetAddress from = new InternetAddress(
1134                    fromAddress, fromName);
1135
1136                InternetAddress to = new InternetAddress(toAddress, toName);
1137
1138                MailMessage message = new MailMessage(
1139                    from, to, subject, body, true);
1140
1141                mailService.sendEmail(message);
1142            }
1143            else if ((remindBy == CalEventImpl.REMIND_BY_AIM) &&
1144                     (Validator.isNotNull(contact.getAimSn()))) {
1145
1146                AIMConnector.send(contact.getAimSn(), body);
1147            }
1148            else if ((remindBy == CalEventImpl.REMIND_BY_ICQ) &&
1149                     (Validator.isNotNull(contact.getIcqSn()))) {
1150
1151                ICQConnector.send(contact.getIcqSn(), body);
1152            }
1153            else if ((remindBy == CalEventImpl.REMIND_BY_MSN) &&
1154                     (Validator.isNotNull(contact.getMsnSn()))) {
1155
1156                MSNConnector.send(contact.getMsnSn(), body);
1157            }
1158            else if ((remindBy == CalEventImpl.REMIND_BY_YM) &&
1159                     (Validator.isNotNull(contact.getYmSn()))) {
1160
1161                YMConnector.send(contact.getYmSn(), body);
1162            }
1163        }
1164        catch (Exception e) {
1165            _log.error(e);
1166        }
1167    }
1168
1169    protected void remindUser(
1170        CalEvent event, User user, Calendar startDate, Calendar now) {
1171
1172        long diff =
1173            (startDate.getTime().getTime() - now.getTime().getTime()) /
1174            CheckEventJob.INTERVAL;
1175
1176        if ((diff == (event.getFirstReminder() / CheckEventJob.INTERVAL)) ||
1177            (diff ==
1178                (event.getSecondReminder() / CheckEventJob.INTERVAL))) {
1179
1180            remindUser(event, user, startDate);
1181        }
1182    }
1183
1184    protected Calendar toCalendar(
1185        DateProperty date, TimeZone timeZone, boolean timeZoneSensitive) {
1186
1187        Calendar cal = null;
1188
1189        if (isICal4jDateOnly(date)) {
1190            cal = Calendar.getInstance();
1191        }
1192        else if (!timeZoneSensitive) {
1193            cal = Calendar.getInstance(TimeZone.getTimeZone(StringPool.UTC));
1194        }
1195        else {
1196            cal = Calendar.getInstance(timeZone);
1197        }
1198
1199        return cal;
1200    }
1201
1202    protected int toCalendarWeekDay(WeekDay weekDay) {
1203        int dayOfWeeek = 0;
1204
1205        if (weekDay.getDay().equals(WeekDay.SU.getDay())) {
1206            dayOfWeeek = Calendar.SUNDAY;
1207        }
1208        else if (weekDay.getDay().equals(WeekDay.MO.getDay())) {
1209            dayOfWeeek = Calendar.MONDAY;
1210        }
1211        else if (weekDay.getDay().equals(WeekDay.TU.getDay())) {
1212            dayOfWeeek = Calendar.TUESDAY;
1213        }
1214        else if (weekDay.getDay().equals(WeekDay.WE.getDay())) {
1215            dayOfWeeek = Calendar.WEDNESDAY;
1216        }
1217        else if (weekDay.getDay().equals(WeekDay.TH.getDay())) {
1218            dayOfWeeek = Calendar.THURSDAY;
1219        }
1220        else if (weekDay.getDay().equals(WeekDay.FR.getDay())) {
1221            dayOfWeeek = Calendar.FRIDAY;
1222        }
1223        else if (weekDay.getDay().equals(WeekDay.SA.getDay())) {
1224            dayOfWeeek = Calendar.SATURDAY;
1225        }
1226
1227        return dayOfWeeek;
1228    }
1229
1230    protected net.fortuna.ical4j.model.Calendar toICalCalendar(
1231        long userId, List<CalEvent> events)
1232        throws PortalException, SystemException {
1233
1234        net.fortuna.ical4j.model.Calendar iCal =
1235            new net.fortuna.ical4j.model.Calendar();
1236
1237        ProdId prodId = new ProdId(
1238            "-//Liferay Inc//Liferay Portal " + ReleaseInfo.getVersion() +
1239            "//EN");
1240
1241        PropertyList props = iCal.getProperties();
1242
1243        props.add(prodId);
1244        props.add(Version.VERSION_2_0);
1245        props.add(CalScale.GREGORIAN);
1246
1247        User user = userPersistence.findByPrimaryKey(userId);
1248        TimeZone timeZone = user.getTimeZone();
1249
1250        List<VEvent> components = iCal.getComponents();
1251
1252        Iterator<CalEvent> itr = events.iterator();
1253
1254        while (itr.hasNext()) {
1255            CalEvent event = itr.next();
1256
1257            components.add(toICalVEvent(event, timeZone));
1258        }
1259
1260        return iCal;
1261    }
1262
1263    protected Recur toICalRecurrence(TZSRecurrence recurrence) {
1264        Recur recur = null;
1265
1266        int recurrenceType = recurrence.getFrequency();
1267
1268        int interval = recurrence.getInterval();
1269
1270        if (recurrenceType == Recurrence.DAILY) {
1271            recur = new Recur(Recur.DAILY, -1);
1272
1273            if (interval >= 1) {
1274                recur.setInterval(interval);
1275            }
1276
1277            DayAndPosition[] byDay = recurrence.getByDay();
1278
1279            if (byDay != null) {
1280                for (int i = 0; i < byDay.length; i++) {
1281                    WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1282
1283                    recur.getDayList().add(weekDay);
1284                }
1285            }
1286
1287        }
1288        else if (recurrenceType == Recurrence.WEEKLY) {
1289            recur = new Recur(Recur.WEEKLY, -1);
1290
1291            recur.setInterval(interval);
1292
1293            DayAndPosition[] byDay = recurrence.getByDay();
1294
1295            if (byDay != null) {
1296                for (int i = 0; i < byDay.length; i++) {
1297                    WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1298
1299                    recur.getDayList().add(weekDay);
1300                }
1301            }
1302        }
1303        else if (recurrenceType == Recurrence.MONTHLY) {
1304            recur = new Recur(Recur.MONTHLY, -1);
1305
1306            recur.setInterval(interval);
1307
1308            int[] byMonthDay = recurrence.getByMonthDay();
1309
1310            if (byMonthDay != null) {
1311                Integer monthDay = new Integer(byMonthDay[0]);
1312
1313                recur.getMonthDayList().add(monthDay);
1314            }
1315            else if (recurrence.getByDay() != null){
1316                DayAndPosition[] byDay = recurrence.getByDay();
1317
1318                WeekDay weekDay = toICalWeekDay(byDay[0].getDayOfWeek());
1319
1320                recur.getDayList().add(weekDay);
1321
1322                Integer position = new Integer(byDay[0].getDayPosition());
1323
1324                recur.getSetPosList().add(position);
1325            }
1326        }
1327        else if (recurrenceType == Recurrence.YEARLY) {
1328            recur = new Recur(Recur.YEARLY, -1);
1329
1330            recur.setInterval(interval);
1331        }
1332
1333        Calendar until = recurrence.getUntil();
1334
1335        if (until != null) {
1336            DateTime dateTime = new DateTime(until.getTime());
1337
1338            recur.setUntil(dateTime);
1339        }
1340
1341        return recur;
1342    }
1343
1344    protected VEvent toICalVEvent(CalEvent event, TimeZone timeZone){
1345        VEvent vEvent = new VEvent();
1346
1347        PropertyList eventProps = vEvent.getProperties();
1348
1349        // UID
1350
1351        Uid uid = new Uid(PortalUUIDUtil.generate());
1352
1353        eventProps.add(uid);
1354
1355        if (event.isAllDay()) {
1356
1357            // Start date
1358
1359            DtStart dtStart = new DtStart(
1360                new net.fortuna.ical4j.model.Date(event.getStartDate()));
1361
1362            eventProps.add(dtStart);
1363
1364            Property dtStartProperty = eventProps.getProperty(Property.DTSTART);
1365
1366            dtStartProperty.getParameters().add(Value.DATE);
1367        }
1368        else {
1369
1370            // Start date
1371
1372            DtStart dtStart = new DtStart(new DateTime(event.getStartDate()));
1373
1374            eventProps.add(dtStart);
1375
1376            // Duration
1377
1378            Duration duration = new Duration(
1379                new Dur(
1380                    0, event.getDurationHour(), event.getDurationMinute(), 0));
1381
1382            eventProps.add(duration);
1383        }
1384
1385        // Summary
1386
1387        Summary summary = new Summary(event.getTitle());
1388
1389        eventProps.add(summary);
1390
1391        // Description
1392
1393        Description description = new Description(event.getDescription());
1394
1395        eventProps.add(description);
1396
1397        // Comment
1398
1399        Comment comment = new Comment(event.getType());
1400
1401        eventProps.add(comment);
1402
1403        // Recurrence rule
1404
1405        if (event.isRepeating()) {
1406            Recur recur = toICalRecurrence(event.getRecurrenceObj());
1407
1408            RRule rRule = new RRule(recur);
1409
1410            eventProps.add(rRule);
1411        }
1412
1413        // Time zone sensitive
1414
1415        if (!event.getTimeZoneSensitive()) {
1416            eventProps.add(new TimeZoneSensitive("FALSE"));
1417        }
1418
1419        return vEvent;
1420    }
1421
1422    protected WeekDay toICalWeekDay(int dayOfWeek) {
1423        WeekDay weekDay = null;
1424
1425        if (dayOfWeek == Calendar.SUNDAY) {
1426            weekDay = WeekDay.SU;
1427        }
1428        else if (dayOfWeek == Calendar.MONDAY) {
1429            weekDay = WeekDay.MO;
1430        }
1431        else if (dayOfWeek == Calendar.TUESDAY) {
1432            weekDay = WeekDay.TU;
1433        }
1434        else if (dayOfWeek == Calendar.WEDNESDAY) {
1435            weekDay = WeekDay.WE;
1436        }
1437        else if (dayOfWeek == Calendar.THURSDAY) {
1438            weekDay = WeekDay.TH;
1439        }
1440        else if (dayOfWeek == Calendar.FRIDAY) {
1441            weekDay = WeekDay.FR;
1442        }
1443        else if (dayOfWeek == Calendar.SATURDAY) {
1444            weekDay = WeekDay.SA;
1445        }
1446
1447        return weekDay;
1448    }
1449
1450    protected TZSRecurrence toRecurrence(
1451        RRule rRule, TimeZone timeZone, Calendar startDate) {
1452
1453        Recur recur = rRule.getRecur();
1454
1455        Calendar recStartCal = CalendarFactoryUtil.getCalendar(timeZone);
1456
1457        recStartCal.setTime(startDate.getTime());
1458
1459        TZSRecurrence recurrence = new TZSRecurrence(
1460            recStartCal,
1461            new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0));
1462
1463        recurrence.setWeekStart(Calendar.SUNDAY);
1464
1465        if (recur.getInterval() > 1){
1466            recurrence.setInterval(recur.getInterval());
1467        }
1468
1469        Calendar until = Calendar.getInstance(timeZone);
1470
1471        String frequency = recur.getFrequency();
1472
1473        if (Validator.isNotNull(recur.getUntil())) {
1474            until.setTime(recur.getUntil());
1475
1476            recurrence.setUntil(until);
1477        }
1478        else if (rRule.getValue().indexOf("COUNT") >= 0) {
1479            until.setTimeInMillis(startDate.getTimeInMillis());
1480
1481            int addField = 0;
1482
1483            if (Recur.DAILY.equals(frequency)) {
1484                addField = Calendar.DAY_OF_YEAR;
1485            }
1486            else if (Recur.WEEKLY.equals(frequency)) {
1487                addField = Calendar.WEEK_OF_YEAR;
1488            }
1489            else if (Recur.MONTHLY.equals(frequency)) {
1490                addField = Calendar.MONTH;
1491            }
1492            else if (Recur.YEARLY.equals(frequency)) {
1493                addField = Calendar.YEAR;
1494            }
1495
1496            int addAmount = recurrence.getInterval() * recur.getCount();
1497
1498            until.add(addField, addAmount);
1499            until.add(Calendar.DAY_OF_YEAR, -1);
1500
1501            recurrence.setUntil(until);
1502        }
1503
1504        if (Recur.DAILY.equals(frequency)) {
1505            recurrence.setFrequency(Recurrence.DAILY);
1506
1507            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1508
1509            Iterator<WeekDay> itr = recur.getDayList().iterator();
1510
1511            while (itr.hasNext()) {
1512                WeekDay weekDay = itr.next();
1513
1514                dayPosList.add(
1515                    new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1516            }
1517
1518            if (!dayPosList.isEmpty()) {
1519                recurrence.setByDay(
1520                    dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1521            }
1522        }
1523        else if (Recur.WEEKLY.equals(frequency)) {
1524            recurrence.setFrequency(Recurrence.WEEKLY);
1525
1526            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1527
1528            Iterator<WeekDay> itr = recur.getDayList().iterator();
1529
1530            while (itr.hasNext()) {
1531                WeekDay weekDay = itr.next();
1532
1533                dayPosList.add(
1534                    new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1535            }
1536
1537            if (!dayPosList.isEmpty()) {
1538                recurrence.setByDay(
1539                    dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1540            }
1541        }
1542        else if (Recur.MONTHLY.equals(frequency)) {
1543            recurrence.setFrequency(Recurrence.MONTHLY);
1544
1545            Iterator<Integer> monthDayListItr =
1546                recur.getMonthDayList().iterator();
1547
1548            if (monthDayListItr.hasNext()) {
1549                Integer monthDay = monthDayListItr.next();
1550
1551                recurrence.setByMonthDay(new int[] {monthDay.intValue()});
1552            }
1553
1554            Iterator<WeekDay> dayListItr = recur.getDayList().iterator();
1555
1556            if (dayListItr.hasNext()) {
1557                WeekDay weekDay = dayListItr.next();
1558
1559                DayAndPosition[] dayPos = {
1560                    new DayAndPosition(toCalendarWeekDay(weekDay),
1561                    weekDay.getOffset())
1562                };
1563
1564                recurrence.setByDay(dayPos);
1565            }
1566        }
1567        else if (Recur.YEARLY.equals(frequency)) {
1568            recurrence.setFrequency(Recurrence.YEARLY);
1569        }
1570
1571        return recurrence;
1572    }
1573
1574    protected void validate(
1575            String title, int startDateMonth, int startDateDay,
1576            int startDateYear, int endDateMonth, int endDateDay,
1577            int endDateYear, int durationHour, int durationMinute,
1578            boolean allDay, boolean repeating)
1579        throws PortalException {
1580
1581        if (Validator.isNull(title)) {
1582            throw new EventTitleException();
1583        }
1584        else if (!Validator.isDate(
1585                startDateMonth, startDateDay, startDateYear)) {
1586
1587            throw new EventStartDateException();
1588        }
1589        else if (!Validator.isDate(endDateMonth, endDateDay, endDateYear)) {
1590            throw new EventEndDateException();
1591        }
1592
1593        if (!allDay && durationHour <= 0 && durationMinute <= 0) {
1594            throw new EventDurationException();
1595        }
1596
1597        Calendar startDate = CalendarFactoryUtil.getCalendar(
1598            startDateYear, startDateMonth, startDateDay);
1599
1600        Calendar endDate = CalendarFactoryUtil.getCalendar(
1601            endDateYear, endDateMonth, endDateDay);
1602
1603        if (repeating && startDate.after(endDate)) {
1604            throw new EventEndDateException();
1605        }
1606    }
1607
1608    private static Log _log =
1609         LogFactoryUtil.getLog(CalEventLocalServiceImpl.class);
1610
1611}